一. 组件动画
在组件上创建和运行动画的快捷方式。具体用法请参考通用方法。
获取动画对象
通过调用 animate 方法获得 animation 对象,animation 对象支持动画属性、动画方法和动画事件。
<!-- xxx.hml --><div class="container"><div id="content" class="box" onclick="Show"></div></div>
/* xxx.css */.container {flex-direction: column;justify-content: center;align-items: center;width: 100%;}.box{width: 200px;height: 200px;background-color: #ff0000;margin-top: 30px;}
/* xxx.js */export default {data: {animation: '',},onInit() {},onShow() {var options = {duration: 1500,};var frames = [{width:200,height:200,},{width:300,height:300,}];this.animation = this.$element('content').animate(frames, options); //获取动画对象},Show() {this.animation.play();}}

说明
● 使用 animate 方法时必须传入 Keyframes 和 Options 参数。
● 多次调用 animate 方法时,采用 replace 策略,即最后一次调用时传入的参数生效。
设置动画参数
在获取动画对象后,通过设置参数 Keyframes 设置动画在组件上的样式。
<!-- xxx.hml --><div class="container"><div id="content" class="box" onclick="Show"></div></div>
/* xxx.css */.container {flex-direction: column;justify-content: center;align-items: center;width: 100%;height: 100%;}.box{width: 200px;height: 200px;background-color: #ff0000;margin-top: 30px;}
/* xxx.js */export default {data: {animation: '',keyframes:{},options:{}},onInit() {this.options = {duration: 4000,}this.keyframes = [{transform: {translate: '-120px -0px',scale: 1,rotate: 0},transformOrigin: '100px 100px',offset: 0.0,width: 200,height: 200},{transform: {translate: '120px 0px',scale: 1.5,rotate: 90},transformOrigin: '100px 100px',offset: 1.0,width: 300,height: 300}]},Show() {this.animation = this.$element('content').animate(this.keyframes, this.options)this.animation.play()}}

说明
● translate、scale 和 rtotate 的先后顺序会影响动画效果。
● transformOrigin 只对 scale 和 rtotate 起作用。
在获取动画对象后,通过设置参数 Options 来设置动画的属性。
<!-- xxx.hml --><div class="container"><div id="content" class="box" onclick="Show"></div></div>
/* xxx.css */.container {flex-direction: column;justify-content: center;align-items: center;width: 100%;}.box{width: 200px;height: 200px;background-color: #ff0000;margin-top: 30px;}
/* xxx.js */export default {data: {animation: '',},onInit() {},onShow() {var options = {duration: 1500,easing: 'ease-in',delay: 5,iterations: 2,direction: 'normal',};var frames = [{transform: {translate: '-150px -0px'}},{transform: {translate: '150px 0px'}}];this.animation = this.$element('content').animate(frames, options);},Show() {this.animation.play();}}

说明
direction:指定动画的播放模式。
normal: 动画正向循环播放。
reverse: 动画反向循环播放。
alternate:动画交替循环播放,奇数次正向播放,偶数次反向播放。
alternate-reverse:动画反向交替循环播放,奇数次反向播放,偶数次正向播放。
二. 插值器动画
动画动效
通过设置插值器来实现动画效果。(从 API Version 6 开始支持。)
创建动画对象
通过 createAnimator 创建一个动画对象,通过设置参数 options 来设置动画的属性。
<!-- xxx.hml --><div class="container"><div style="width: 300px;height: 300px;margin-top: 100px;background: linear-gradient(pink, purple);transform: translate({{translateVal}});"></div><div class="row"><button type="capsule" value="play" onclick="playAnimation"></button></div></div>
/* xxx.css */.container {width:100%;height:100%;flex-direction: column;align-items: center;justify-content: center;}button{width: 200px;}.row{width: 65%;height: 100px;align-items: center;justify-content: space-between;margin-top: 50px;margin-left: 260px;}
// xxx.jsimport animator from '@ohos.animator';export default {data: {translateVal: 0,animation: null},onInit() {},onShow(){var options = {duration: 3000,easing:"friction",delay:"1000",fill: 'forwards',direction:'alternate',iterations: 2,begin: 0,end: 180};//设置参数this.animation = animator.createAnimator(options)//创建动画},playAnimation() {var _this = this;this.animation.onframe = function(value) {_this.translateVal= value};this.animation.play();}}

说明
● 使用 createAnimator 创建动画对象时必须传入 options 参数。
● begin 插值起点,不设置时默认为 0。
● end 插值终点,不设置时默认为 1。
添加动画事件和调用接口
animator 支持事件和接口,可以通过添加 frame、cancel、repeat、finish 事件和调用 update、play、pause、cancel、reverse、finish 接口自定义动画效果。animator 支持的事件和接口具体见动画中的createAnimator。
<!-- xxx.hml --><div style="flex-direction: column;align-items: center;width: 100%;height: 100%;"><div style="width:200px;height: 200px;margin-top: 100px;background: linear-gradient(#b30d29, #dcac1b);transform: scale({{scaleVal}});"></div><div style="width: {{DivWidth}};height: {{DivHeight}};margin-top: 200px;background: linear-gradient(pink, purple);margin-top: 200px;transform:translateY({{translateVal}});"></div><div class="row"><button type="capsule" value="play" onclick="playAnimation"></button><button type="capsule" value="update" onclick="updateAnimation"></button></div><div class="row1"><button type="capsule" value="pause" onclick="pauseAnimation"></button><button type="capsule" value="finish" onclick="finishAnimation"></button></div><div class="row2"><button type="capsule" value="cancel" onclick="cancelAnimation"></button><button type="capsule" value="reverse" onclick="reverseAnimation"></button></div></div>
/* xxx.css */button{width: 200px;}.row{width: 65%;height: 100px;align-items: center;justify-content: space-between;margin-top: 150px;position: fixed;top: 52%;left: 120px;}.row1{width: 65%;height: 100px;align-items: center;justify-content: space-between;margin-top: 120px;position: fixed;top: 65%;left: 120px;}.row2{width: 65%;height: 100px;align-items: center;justify-content: space-between;margin-top: 100px;position: fixed;top: 75%;left: 120px;}
// xxx.jsimport animator from '@ohos.animator';import promptAction from '@ohos.promptAction';export default {data: {scaleVal:1,DivWidth:200,DivHeight:200,translateVal:0,animation: null},onInit() {var options = {duration: 3000,fill: 'forwards',begin: 200,end: 270};this.animation = animator.createAnimator(options);},onShow() {var _this= this;//添加动画重放事件this.animation.onrepeat = function() {promptAction.showToast({message: 'repeat'});var repeatoptions = {duration: 2000,iterations: 1,direction: 'alternate',begin: 180,end: 240};_this.animation.update(repeatoptions);_this.animation.play();};},playAnimation() {var _this= this;//添加动画逐帧插值回调事件this.animation.onframe = function(value) {_this. scaleVal= value/150,_this.DivWidth = value,_this.DivHeight = value,_this.translateVal = value-180};this.animation.play();},updateAnimation() {var newoptions = {duration: 5000,iterations: 2,begin: 120,end: 180};this.animation.update(newoptions);this.animation.play();//调用动画播放接口},pauseAnimation() {this.animation.pause();//调用动画暂停接口},finishAnimation() {var _this= this;//添加动画完成事件this.animation.onfinish = function() {promptAction.showToast({message: 'finish'})};this.animation.finish(); //调用动画完成接口},cancelAnimation() {this.animation.cancel(); //调用动画取消接口},reverseAnimation() {this.animation.reverse(); //调用动画倒放接口}}

说明
在调用 update 接口的过程中可以使用这个接口更新动画参数,入参与 createAnimator 一致。
动画帧
请求动画帧
请求动画帧时通过 requestAnimationFrame 函数逐帧回调,在调用该函数时传入一个回调函数。
runframe 在调用 requestAnimationFrame 时传入带有 timestamp 参数的回调函数 step,将 step 中的 timestamp 赋予起始的 startTime。当 timestamp 与 startTime 的差值小于规定的时间时将再次调用 requestAnimationFrame,最终动画将会停止。
<!-- xxx.hml --><div class="container"><tabs onchange="changecontent"><tab-content><div class="container"><stack style="width: 300px;height: 300px;margin-top: 100px;margin-bottom: 100px;"><canvas id="mycanvas" style="width: 100%;height: 100%;background-color: coral;"></canvas><div style="width: 50px;height: 50px;border-radius: 25px;background-color: indigo;position: absolute;left: {{left}};top: {{top}};"></div></stack><button type="capsule" value="play" onclick="runframe"></button></div></tab-content></tabs></div>
/* xxx.css */.container {flex-direction: column;justify-content: center;align-items: center;width: 100%;height: 100%;}button{width: 300px;}
// xxx.jsexport default {data: {timer: null,left: 0,top: 0,flag: true,animation: null,startTime: 0,},onShow() {var test = this.$element("mycanvas");var ctx = test.getContext("2d");ctx.beginPath();ctx.moveTo(0, 0);ctx.lineTo(300, 300);ctx.lineWidth = 5;ctx.strokeStyle = "red";ctx.stroke();},runframe() {this.left = 0;this.top = 0;this.flag = true;this.animation = requestAnimationFrame(this.step);},step(timestamp) {if (this.flag) {this.left += 5;this.top += 5;if (this.startTime == 0) {this.startTime = timestamp;}var elapsed = timestamp - this.startTime;if (elapsed < 500) {console.log('callback step timestamp: ' + timestamp);this.animation = requestAnimationFrame(this.step);}} else {this.left -= 5;this.top -= 5;this.animation = requestAnimationFrame(this.step);}if (this.left == 250 || this.left == 0) {this.flag = !this.flag}},onDestroy() {cancelAnimationFrame(this.animation);}}

说明
requestAnimationFrame 函数在调用回调函数时在第一个参数位置传入 timestamp 时间戳,表示 requestAnimationFrame 开始去执行回调函数的时刻。
取消动画帧
通过 cancelAnimationFrame 函数取消逐帧回调,在调用 cancelAnimationFrame 函数时取消 requestAnimationFrame 函数的请求。
<!-- xxx.hml --><div class="container"><tabs onchange="changecontent"><tab-content><div class="container"><stack style="width: 300px;height: 300px;margin-top: 100px;margin-bottom: 100px;"><canvas id="mycanvas" style="width: 100%;height: 100%;background-color: coral;"></canvas><div style="width: 50px;height: 50px;border-radius: 25px;background-color: indigo;position: absolute;left: {{left}};top: {{top}};"></div></stack><button type="capsule" value="play" onclick="runframe"></button></div></tab-content></tabs></div>
/* xxx.css */.container {flex-direction: column;justify-content: center;align-items: center;width: 100%;height: 100%;}button{width: 300px;}
// xxx.jsexport default {data: {timer: null,left: 0,top: 0,flag: true,animation: null},onShow() {var test = this.$element("mycanvas");var ctx = test.getContext("2d");ctx.beginPath();ctx.moveTo(0, 0);ctx.lineTo(300, 300);ctx.lineWidth = 5;ctx.strokeStyle = "red";ctx.stroke();},runframe() {this.left = 0;this.top = 0;this.flag = true;this.animation = requestAnimationFrame(this.step);},step(timestamp) {if (this.flag) {this.left += 5;this.top += 5;this.animation = requestAnimationFrame(this.step);} else {this.left -= 5;this.top -= 5;this.animation = requestAnimationFrame(this.step);}if (this.left == 250 || this.left == 0) {this.flag = !this.flag}},onDestroy() {cancelAnimationFrame(this.animation);}}

说明
在调用该函数时需传入一个具有标识 id 的参数。
2746

被折叠的 条评论
为什么被折叠?



