多段动画整合为一个动画的思路

更新日期: 2019-10-12阅读: 2.5k标签: 动画

需求

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

我们的开发人员首先想到的思路是,把获取的点位列表信息,每两个取取来,组成一条直线路径。然后基于每一条直线路径,创建一个动画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彪叔”。


链接: https://www.fly63.com/article/detial/6810

纯CSS3实现各种表情动画

CSS3非常强大,我们可以利用CSS3相关特性绘制很多平面图形,并且可以制作很多简单的动画。今天要分享的是一款用纯CSS3实现的可爱表情动画

Vue.js动画笔记_vue实现动画效果

Vue.js中的元素动画或页面跳转动画有多种实现方式比如:1、自己手动写CSS3动画来实现2、使用第三方CSS动画库如:Animate.css3、在构子函数中操作DOM4、使用第三方Js动画库如:Velocity.js。

新手引导动画的4种实现方式

尽量多的列举出新手引导动画的实现方式, 昨天稍微总结了一下, 实现了4种.源码在最后,如果想直接看结果的,可以拉到最后去看.这里假设所有的弹出层都是基于页面上原有的元素

为何 Canvas 内元素动画总是在颤抖?

在项目中我们可能对动画进行锁帧,帧率可能是 60 或者 30,如果我们想保证渲染不抖动,在匀速直线运动中,我们尽量保证我们设置的速度要是帧率的倍数,或者保证平均每帧移动的像素点是一样的

前端开发常用css动画代码

常用的CSS动画效果,在实际开发中经常需要用到移动、大小、闪烁、渐显、渐隐等动画效果,这篇文章就整理了些常见的动画效果分享给大家,一遍收藏使用。

css环形滚动_内容加载的环形滚动动画效果

创建一个没有背景的圆,然后声明透明度为0.1的黑色边框(看起来是灰色),修改左侧边框颜色。此时会有一个静态的看起来只有左边框有颜色的空心圆。然后声明一个该元素逆时针旋转360度的动画,并让该动画无限播放(infinite)即可

css transition 实现滑入滑出

transition是css最简单的动画。 通常当一个div属性变化时,我们会立即看的变化,从旧样式到新样式是一瞬间的,嗖嗖嗖!!!但是,如果我希望是慢慢的从一种状态,转变成另外一种状态,怎么办? transition可以做到。

动画函数的绘制及自定义动画函数

制作动画效果离不开动画运动函数,而我们用得最多的无疑就是Tween.js。根据不同的数学公式原理,Tween.js划分出了不同的动画类型,每种动画类型里面都包含以下的缓动类型:ease in 先慢后快、ease out 先块后慢、ease in out 先慢后快再慢

超酷的CSS3 loading预加载动画特效

这是一款超酷CSS3 loading预加载动画特效。该loading特效共有4种不同的效果,分别通过不同的CSS3 keyframes帧动画来完成。HTML结构:4种loading预加载动画的HTML结构分别如下

Vue 动画的封装

js提供的钩子动画before-enter、enter、after-enter,用这种方法写,所有的动画都写在了组件里,外部只需要调用这个fade组件就可以了,也不需要全局去写一些样式了,这种动画的封装是比较推荐的一种动画封装,因为它可以把所有动画的实现完整的封装在一个组件中

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!