开发指导—利用组件插值器动画实现 HarmonyOS 动效

news2024/12/25 9:18:00

一. 组件动画

在组件上创建和运行动画的快捷方式。具体用法请参考通用方法。

获取动画对象

通过调用 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 的参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/975005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IntelliJ IDEA中用git提交代码时忽略文件的设置

设置IDEA自动过滤掉不需要提交的文件或文件夹&#xff1a;如*.iml, .idea,target 文件夹 1、进入idea设置界面 Windows环境&#xff1a;File - Settings - Editor - File Types Mac环境&#xff1a;Preferences… - Editor - File Types 2、在下面的ignore files and folders…

SPA和MPA

SPA与MPA是什么 **SPA&#xff08;Single Page Application&#xff0c;单页应用&#xff09;**在首次加载时会下载一个单独的HTML文件&#xff0c;然后通过JavaScript动态加载内容&#xff0c;无需每次页面刷新时重新加载整个页面。**MPA&#xff08;Multi-Page Application&…

【校招VIP】java语言考点之关键字string

考点介绍&#xff1a; string作为一个特殊类&#xff0c;正常情况下&#xff0c;是遵循对象的值和引用的使用。有一定的考察频度&#xff0c;但有的时候也能代表相等&#xff0c;与常量区的插入有关。 java语言考点之关键字string-相关题目及解析内容可点击文章末尾链接查看&a…

redis缓存失效时间没到,数据莫名丢失问题排查

述&#xff1a;redis缓存了token&#xff0c;失效时间为24小时&#xff0c;可是每次不到多久&#xff0c;就提示token失效&#xff0c;重新登录后&#xff0c;没用多久&#xff0c;又提示token失效。查看了下缓存&#xff0c;发现数据全部没掉了&#xff0c;并且多了几个back1&…

电脑提示“系统找不到指定的文件”怎么办?

“系统找不到指定的文件”对于Windows用户来说是一个很常见的错误&#xff0c;尤其是Win10用户&#xff0c;经常会遇到Win10提示找不到指定文件。在此错误后面有时还会出现错误代码&#xff1a;0x80070002&#xff0c;但是&#xff0c;故障类型或代码在不同的操作系统规范上是不…

史上最全PMP学习资料、项目管理资料、备考经验包,3A一次通过

你是否也有过类似的经历&#xff1f; 为了获取备考资料&#xff0c;有的同学在论坛、知乎或者相关垂直类网站下载了很多的资料&#xff0c;这些资料大部分是机构进行获客引流的资料&#xff0c;没有真正的干货。 经常会看到10G、20G的资料包&#xff0c;感觉内容很丰富&#xf…

Spring学习|Spring简介、IOC控制反转理解、IOC创建对象方式

Spring Spring:春天------>给软件行业带来了春天! 2002&#xff0c;首次推出了Spring框架的雏形: interface21框架! Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版。 RodJohnson&#xff0c;Spring Framework创始人&…

关于某次授权的大型内网渗透测试

背景&#xff1a; 接到朋友邀请&#xff0c;要进行一个授权站点的渗透&#xff0c;但是进去实际环境才发现是多域控主机。也学习了很多后渗透手法&#xff0c;比较受益匪浅。 前期渗透&#xff1a; 打点&#xff1a;&#xff08;任意文件上传&#xff09; 直接发现头像处任…

目录与文件系统

无论在哪个计算机系统中&#xff0c;文件系统结构都应该是一样的一层或者几层的话太多太乱不适用用目录实现一个树状结构&#xff0c;划分后层次清晰如果把目录下所有的文件的FCB都存取&#xff0c;然后对比没必要太麻烦了 所以数据盘块集合中存放目录下文件字符串和对应的编号…

Rocky(Centos)安装中文字体(防止中文乱码)

1、查看字体列表 运行下列命令 fc-list 若出现&#xff0c;下面截图&#xff0c;则需要安装字体管理软件 安装字体库&#xff0c;运行&#xff1a; yum -y install fontconfig 当看到下图的提示信息时说明已安装成功&#xff1a; 二、添加中文字体 1&#xff09;window…

文件夹怎么安全加密?文件夹加密软件怎么样?

我们在使用电脑的过程中&#xff0c;习惯用文件夹来管理电脑数据&#xff0c;为了文件夹数据安全&#xff0c;我们需要使用加密的方式来进行保护。那么&#xff0c;文件夹该怎么安全加密呢&#xff1f;下面我们就来了解一下。 文件夹加密软件安全吗&#xff1f; 文件夹加密软…

功率放大器主要作用是什么呢

功率放大器是一种电子设备&#xff0c;主要作用是将输入信号的功率增加到更高的水平&#xff0c;以便能够驱动高功率负载。在许多应用中&#xff0c;信号源产生的信号往往具有较低的功率&#xff0c;无法直接满足一些要求较高的设备或系统的需求。而功率放大器则可以增强信号的…

当面试被问到 Java 内存模型,不妨反问面试官:您问得是 Java Memory Model 呢?还是 JVM 运行时数据区?

目录 1. JVM 运行时数据区 2. Java 内存模型 最近在牛客上看到这样一个帖子&#xff0c;大概就是在面试中呢&#xff0c;被面试官问到了 Java 内存模型&#xff0c;面试的这位小伙呢&#xff0c;也是掌握了 JVM 内存布局的相关知识&#xff0c;但是不知道面试官问的 Java 内存…

行测图形推理规律(一)元素组成

题库&#xff1a;粉笔网题库 (fenbi.com) 不知道和测评的行测题库是不是一样的&#xff0c;但是总结的规律应该是一样的。 规律并不唯一&#xff0c;题库的答案也只是参考答案&#xff0c;切勿当杠精&#xff0c;你觉得你的规律更合适就别管。本人所归纳的规律仅代表本人想法…

淘宝数据库,主键如何设计的?

聊一个实际问题&#xff1a;淘宝的数据库&#xff0c;主键是如何设计的&#xff1f; 某些错的离谱的答案还在网上年复一年的流传着&#xff0c;甚至还成为了所谓的 MySQL 军规。其中&#xff0c;一个最明显的错误就是关于MySQL 的主键设计。 大部分人的回答如此自信&#xff…

uni-app点击复制指定内容(点击复制)

官方api uni.setClipboardData(OBJECT) uni.setClipboardData({data: 要被复制的内容,success: function () {console.log(success);} });

虹科分享 | MKA:基于先进车载网络安全解决方案的密钥协议

MKA作为MACsec的密钥协议&#xff0c;具有安全、高效、针对性强的特点&#xff0c;为您的汽车ECU通讯创建了一个安全的通信平台&#xff0c;可以助力您的各种汽车创新项目&#xff01; 虹科方案 | 什么是基于MACsec的汽车MKA 一、MACsec在汽车行业的应用 在以往的文章中&#…

AutoSAR-BSW层概述

一.什么是BSW BSW层全称为Basic Software &#xff08;基础软件层&#xff09;&#xff0c;顾名思义&#xff0c;该层主要是为应用层提供基础服务。 这里可以看到 BSW 主要提供了&#xff1a;看门狗服务 &#xff0c;存储服务&#xff0c;通信和诊断服务&#xff0c;OS服务&a…

select 语句执行顺序

sql 样例 select t_students.name as 姓名, sum(case when b.cname语文 then c.sc_val else 0 end) As 语文 ,sum(case when b.cname数学 then c.sc_val else 0 end) As 数学,sum(case when b.cname英语 then c.sc_val else 0 end) As 英语, From t_students a, t_corses b, t…

MIT6.S081实验环境搭建

MIT6.S081 lab 环境搭建 本文参考了MIT的官方指南和知乎文章环境搭建 step1 首先需要一个ubuntu20.04的系统&#xff0c;我使用的是vscode的WSL2连接的ubuntu20.04&#xff0c;使用virtual box建一个ubuntu20.04的虚拟机应该也可以。 可以用 lsb_release -a 查看一下自己ub…