多段动画整合为一个动画的思路基础知识入门_动画入门百科

需求这是从一个项目中提取的需求。 大致的思路是: 通过获取后端的一系列人员的点位信息,在前端模拟人员的一段时间内的行动过程。我们的开发人员首先想到的思路是,把获取的点位列表信息,每两个取取来,组成一条直线路径。然后基于每一条直线路径,创建一个动画Animate对象。(Animate是我们内部的一个管理/播放动画的类)。其中创建每一个Animate动画的代码大

多段动画整合为一个动画的思路基础知识入门

需求

这是从一个项目中提取的需求。 大致的思路是: 通过获取后端的一系列人员的点位信息,在前端模拟人员的一段时间内的行动过程。

多段动画整合为一个动画的思路基础知识入门_动画入门百科

我们的开发人员首先想到的思路是,把获取的点位列表信息,每两个取取来,组成一条直线路径。然后基于每一条直线路径,创建一个动画Animate对象。(Animate是我们内部的一个管理/播放动画的类)。

其中创建每一个Animate动画的代码大致如下:

new Animate({
    from: p1,
    to : p2,
    dur : 30 * 1000,
    onUpdate(p){
       persion.setPosition(p)
    }
});

上述代码中,创建了一个动画对象,其参数表示如下:

  • from : p1, 动画开始的位置
  • to : p2,动画结束的位置
  • dur: 动画持续的时间
  • onUpdate函数,Animate对象内部更新处理每一帧数据的回调函数, Animate对象会根据from和 to以及dur的值,结合当前这一块的时间戳。计算出每一帧的插值数据p,并把p传递给回调函数onUpdate, 我们可以在onUpdate接收每一帧的数据值,并进行我们的更新动作,比如在本实例中会根据接收到的定向信息更新人员的位置信息。

问题

这个思路初期时没有问题的,只是到了实测的时候,发现性能有挺大的问题。因为获取一天的点位信息,点位的数量大概在几天条,这就意味这需要持续创建几千个Animate对象。这必然会造成性能问题。

在了解了这个问题之后,我建议我们的开发人员值只创建一个Animate对象,把所有直线路径的动画都整合到该Animate对象中。

要把所有的路径动画包含到一个Animate对象中,第一步是要改造from和to的值,此时不能直接使用点位信息来作为from和to的值。 实际上,我们可以通过百分比的方式来设置from和to,即from等于0,to等于1(相当于100%)。

为了简化问题,我们首先看只有一条直线的情况下,from和to设置位百分比是如何实现的。代码如下:

var p1, p2;
...
new Animate({
    from: 0,
    to : 1,
    dur : 30 * 1000,
    onUpdate(value){ 
       var p = lerpVectors(p1,p2,value);
       persion.setPosition(p)
    }
});

当把from和to设置位百分比时,Animate计算出来的每一帧的数值value是一个0~1之间的百分比值。此时,我们在onUpdate函数中,自己通过插值计算来计算点位信息p(其中lerpVectors函数完成此功能,此处不详述)。

整合思路

然后,我们在看多条直线的情况。 这种情况下的难点在于,要把一个动画分割成多段动画。然后对于分割的每一段,启动上面实例中的0~1的过程动画。其中涉及到两个问题

  1. Animate给定的value值,我们如何确定要执行的是那一段动画。
  2. 确定了那一段之后,如何把value值转换位这一段动画(从0~1)的动画值。

确定索引值

对于第一个问题,由需求有关。本文中,所有要执行动画的片段,其时间是一样的,这样就意外这,所有段的分配值是平均的。 举个例子,由10条直线组成动画,对于0~1之间的value值,由:

  • 0~0.1 执行第一条直线的动画
  • 0.1~0.2 执行第二条直线的动画
  • 依次类推。。。

因此我们可以通过循环变量和值比较来确定要执行动画直线的索引值,比如如下代码:

var index = 0;
for(var  i = 0;i < len;i ++){
  if(value > i / len && value < (i + 1) / len){
     index = i;
    break;
  }
}

上述代码中,首先启动以一个循环,循环的长度位片段的数量长度len。在循环体内,比较value值是否在索引i分片所对应的区间之内,如果在区间,就让index = i,以此确定要执行第index条直线的动画。

当然,如果通过数学公式,可以更加方便确定索引值index。怎么处理呢?

首先把0~1的范围扩展到0~len,此时把value值也乘以len,一样的道理,假设如果value * len的结果:

  • 在0~1之间,则value值对应的是第一分片的动画
  • 在1~2之间,则value值对应的是第二分片的动画
  • 在len – 1 ~ len之间,则value值对应的是第二分片的动画

因此只要看value*len在那个整数区间即可,只是确定一个数值的整数区间,不在需要通过遍历,而只需要一个数学的函数即可:Math.floor。因此可以通过下述一行代码既可快速确定索引值:

var index = Math.floor(value * len);

确定每一段动画的帧数值

上面确定了索引值。 如何确定每段动画的的帧数值呢? 起始很简单,我们知道value * len一定在index ~ index + 1 之间。 那么可以通过平移把区间index ~ index + 1 平移到区间0~1即可。 平移只需要减去index即可。代码如下: ··· var valueOfSegment = value * len – index; ···

上代码

下面是比较完整的代码(伪代码):

var lines = [];// 要播放动画的一系列直线;
var len = lines.length;
new Animate({
    from: 0,
    to : 1,
    dur : 30 * 1000,
    onUpdate(value){ 
       var index = Math.floor(value * len);
       var valueOfSegment = value * len - index;
       var line = lines[index];
        var p1 = line.p1,p2 = line.p2;
       var p = lerpVectors(p1,p2,value);
       persion.setPosition(p)
    }
});

总结

把多个动画整合位一个,是在动画很多的时候,提高性能的一个有效手段。

善于利用数学公式,可以有效提高代码编写效率,本文中两个重要的公式如下, 具体作用见上面正文:

   var index = Math.floor(value * len);
   var valueOfSegment = value * len - index;

欢迎关注公众号“ITman彪叔”。

海计划公众号
(0)
上一篇 2020/03/23 18:37
下一篇 2020/03/23 18:37

您可能感兴趣的内容

  • 发布-订阅模式和观察者模式真的不一样?小白攻略_模式使用说明

    背景设计模式的定义: 在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。设计模式并不能直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案,它不是一个死的机制,它是一种思想,一种代码的形式。每种语言对于各种设计模式都要它们自己的实现方式,对于某些设计模式来说,可能在某些语言下并不适用,比如工厂模式就不适用于JavaSctipt

    2020/03/26
  • vue-lazyload小白攻略_vue中使用图片懒加载插件

    vue-lazyload小白攻略 官方网址:http://hilongjw.github.io/vue-lazyload/ GitHub:https://github.com/hi…

    2020/03/06
  • javascript中什么是访问器属性?基础入门_属性入门攻略

    访问器属性不包含数据值。它包含一对getter和setter函数。当读取访问器属性时,会调用getter函数并返回有效值;当写入访问器属性时,会调用setter函数并传入新值,setter函数负责处理数据。一.访问器属性定义:访问器属性由get和set方法定义。(1).读取属性的时候调用get方法。(2).设置属性的时候调用set方法。let web={_w

    2020/03/20
  • vue3 实现 v-model 原理基础教程_原理入门教程

    vue3 源码正式放出来了,想必大家也都开始争先恐后的学习 vue3 的知识了。由于 vue3 已经不再支持 v-model 了,而使用 .sync 来代替,但是为了这篇文章可以帮助大家快速了解 vue 的双向绑定实现原理,部分使用了 vue2.x v-model 的实现原理proxy 的基础知识,相信大家已经都很了解了,让我们一起来回顾一下吧:proxy

    2020/03/23
  • 浏览器事件模型入门基础_模型菜鸟教程

    什么是事件我想你很可能听说过事件驱动, 但是事件驱动到底是什么?为什么说浏览器是事件驱动的呢?为什么 NodeJS 也是事件驱动的 ? 两者是一回事么?实际上不管是浏览器还是 Nodejs 都是事件驱动的,都有自己的事件模型。在这里,我们只讲解浏览器端的事件模型,如果对 Nodejs 事件模型感兴趣的,请期待我的 Nodejs 部分的讲解。事件驱动通俗地来说

    2020/03/23
  • vue.js有哪些特点?使用攻略_特点菜鸟教程网

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,并且非常容易学习,也非常容易与其他库或已有项目整合。Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用。Vue.js 还提供了 M

    2020/03/31
  • XD资源网基础入门_专业的adboexd资源社区

    XD资源网基础入门 官方网址:https://www.xdccpro.com/ 简介描述:专业的adboexd资源社区 XD资源网是一个专业的AdobeXD资源社区,提供Adobe…

    2020/03/06
  • 用lnmp架构部署wordpress网站详细步骤入门攻略_wordpress使用帮助

    用lnmp架构部署wordpress网站①.下载和上传网站代码 用winscp或者xftp, 或者xshell下执行rz命令进行上传网站的包文件.②.解压程序代码,并将程序代码保存到站点目录,并进行授权chown -R nginx.nginx /app/nginx/html/blog/ (将站点目录授权给nginx的运行用户)ll /app/nginx/

    2020/04/03
  • lightweight-charts使用教程_最小和最快的金融HTML5图表

    lightweight-charts使用教程 官方网址:https://www.tradingview.com/HTML5-stock-forex-bitcoin-charting…

    2020/03/10
  • javascript是编译型还是解释型?基础指南_语言攻略教程

    javascript是解释型的,是直译式脚本语言。javascript是不需要编译的,浏览器直接解释源代码,并执行在内存中创建变量等操作。什么是编译型?编译型语言是把源代码先编译为机器码(也就是所谓的可执行程序,比如windows系统的exe文件),运行的时候电脑只需直接把机器码交给CPU执行即可。编译型语言的特点是运行速度快,效率高。缺点是可移植性差。什么

    2020/03/22
  • html如何把图片大小变小?菜鸟教程下载_图片入门指南

    我们在布局图片列表时,通常我们要控制图片的高度和宽度这样来达到图片统一。我们在HTML布局时候直接在图片img标签加宽度和高度属性即可控制图片高和宽。一、html img图片标签高度宽度设置我们可以直接在图片标签设置宽度width和高度height,这里需要注意的是HTML img标签内直接设置宽度和高度值不需要html单位,默认为PX像素。<img src

    2020/03/31
  • proppy.js基础指南_UI组件的功能道具组合(React.js和Vue.js)

    proppy.js基础指南 官方网址:https://proppyjs.com GitHub:https://github.com/fahad19/proppy 简介描述:UI组件…

    2020/03/06
  • waterfall使用攻略_jquery 瀑布流布局插件, 类似于 Pinterest

    waterfall使用攻略 官方网址:http://wlog.cn/waterfall/ GitHub:https://github.com/bingdian/waterfall …

    2020/03/10
  • json与jsonp的使用小白常识_json使用帮助

    1.json与jsonp的引入在ajax中 JSON用来解决数据交换问题,而JSONP来实现跨域。备注:跨域也可以通过服务器端代理来解决;理解:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。2.JSON:是一种基于文本的数据交换方式,或者叫做数据描述格式,是否该选用它首先肯定要关注它所拥有的优点。 J

    2020/03/22
  • new,call,apply,bind方法的实现原理菜鸟教程下载_原理小白入门

    javascript中new,call,apply,bind等方法是我们经常要使用到,在伪数组转数组、函数传参、继承等场景中,都离不开他们。这里就不具体讨论他们的使用方法,我们将研究他们的实现方式,重写属于我们自己的方法,让大家重新认识他们的实现过程,使我们在开发中知其然,知其所以然!new的实现我们用new实例化一个构造函数,生成一个实例对象,而new到底

    2020/03/24
  • Smashingmagazine使用攻略一个web技术类的博客杂志站点

    Smashingmagazine基础入门 官方网址:https://www.smashingmagazine.com/ 简介描述:一个web技术类的博客杂志站点

    2020/03/05