当前位置: 首页 > Web前端 > HTML5

将多个动画整合为一个动画的想法

时间:2023-04-05 20:59:51 HTML5

需求这是从一个项目中抽取出来的需求。大致思路是:通过在后端获取一系列人员的点位信息,在前端模拟人员在一段时间内的动作过程。我们开发人员第一个想到的想法是,每隔两个取一次获取的点列表信息,形成一条直线路径。然后根据每条直线路径,创建一个动画Animate对象。(Animate是我们管理/播放动画的内部类)。创建每个Animate动画的代码大致如下:newAnimate({from:p1,to:p2,dur:30*1000,onUpdate(p){persion.setPosition(p)}});在上面的代码中,创建了一个动画对象,其参数表示如下:from:p1,动画开始位置to:p2,动画结束位置dur:动画持续时间onUpdate函数,Animate对象内部的更新回调函数来处理每一帧的data,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设置位百分比是如何实现的。代码如下:varp1,p2;...newAnimate({from:0,to:1,dur:30*1000,onUpdate(value){varp=lerpVectors(p1,p2,value);period.setPosition(p)}});当from和to设置为百分比时,Animate计算的每一帧的数值都是0到1之间的百分比值。此时在onUpdate函数中,我们通过插值计算的方式计算点信息p(lerpVectors函数完成这个功能,这里就不详细介绍了)。整合思路那么,我们在看多条直线的情况。这种情况下的难点在于将一个动画拆分成多个动画。然后对于每段划分,开始上例中0~1的过程动画。Animate给出的value值涉及到两个问题,我们如何确定执行哪个动画。确定了那段之后,如何把值转换成这段动画的动画值(从0到1)。第一个问题的指标值根据需求确定。在这篇文章中,所有要动画的片段都有相同的时间,所以一不小心,所有片段的分布值都是平均的。例如动画由10条直线组成。对于0到1之间的值,第一条直线的动画在0~0.1执行,第二条直线的动画在0.1~0.2执行,以此类推。..因此,我们可以通过比较循环变量和值来确定要执行的动画行的索引值,比如下面的代码:varindex=0;for(vari=0;ii/len&&值<(i+1)/len){index=i;休息;}}上面的代码中,首先开始了一个循环,循环的长度为分片的个数,长度为len。在循环体中,比较该值是否在索引i切片对应的区间内,如果在区间内则令index=i,从而判断执行索引线的动画。当然,如果使用数学公式,可以更方便地确定指标值指标。如何处理?首先将0~1的范围扩大到0~len,然后将value乘以len,同理,假设如果value*len:的结果在0~1之间,那么这个value对应的是第一个如果动画slice的值在1和2之间,value值对应第二个slice的动画。如果在len-1~len之间,则该值对应第二个切片的动画。所以只看value*len可以在整数区间,只是确定一个值的整数区间,不需要遍历,只需要一个数学函数:Math.floor。因此,可以通过下面一行代码快速确定索引值:varindex=Math.floor(value*len);确定每个动画的帧值索引值在上面确定。如何确定每个动画的帧值?开始很简单,我们知道value*len一定在index~index+1之间。然后你可以通过翻译将区间index~index+1翻译成区间0~1。翻译只需要减去索引即可。代码如下:···varvalueOfSegment=value*len-index;···下面的代码是比较完整的代码(伪代码):varlines=[];//一系列的直线来播放动画;varlen=lines.length;newAnimate({from:0,to:1,dur:30*1000,onUpdate(value){varindex=Math.floor(value*len);varvalueOfSegment=value*len-index;varline=lines[index];varp1=line.p1,p2=line.p2;varp=lerpVectors(p1,p2,value);persion.setPosition(p)}});总结一下将多个动画整合为一个,是在动画较多的情况下提升性能的有效手段。善于运用数学公式可以有效提高代码编写的效率。本文中的两个重要公式如下。具体函数见上文:varindex=Math.floor(value*len);varvalueOfSegment=值*len-索引;欢迎关注公众号“IT人飚大叔”。飚叔,10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。对计算机图形学、WebGL、前端可视化有深入研究。对程序员思维能力的训练与训练,程序员职业生涯规划有着浓厚的兴趣。