遇到动画需求,应该用什么方法来实现呢?这里我大致分为4种情况,gif图片/动画/ae导出骨骼动画/ae导出canvas1。gif图片的硬核解法没错!最简单的方法就是让我们的设计师直接给我们gif图片,那么在我们的前端,这只是一个图片问题,我们只需要控制显示和隐藏就可以了。这简直是??最舒服的方式。那么gif动画动画有哪些缺点呢?添加一些效果时,会出现锯齿,色值不丰富;如果有多个gif同时并行播放,这时候就会出现问题。让我们来看看问题是什么。假设有这样一个场景:在一个列表中,当用户点击列表中的每一项时,项的中间会出现一朵盛开的烟花。简单的!马上给你写信!exportclassItemextendsComponent{timer:NodeJS.Timeoutplaying(){if(this.timer){clearTimeout(this.timer);}this.setState({fire:true});this.timer=setTimeout(()=>{this.setState({fire:false});},1500);}render(){return(
我要放烟花!
{this.state.fire?{dataList.map((data)=>{return })}
);}}假设我们现在的烟花gif是1500ms循环播放的,那么用户点击列表顺序的item是什么现象呢?当用户点击第一个时em,第一项的烟花在此时绽放;用户在500ms后点击第二个item,第二个item上的烟花会和第一个item的烟花保持相同的节奏,即第二个item的烟花在500ms开始播放,持续1000ms;用户在1000ms后点击第三项,第三项的烟花与前两项的烟花节奏相同,即第三项的烟花在1000ms开始播放,持续时间为500ms;但是我们的定时器傻傻的设置为1500ms,那么在第二个item上的烟花绽放一次之后,还有500ms可以播放烟花的前500ms,第三个item上的烟花也是如此;这是个问题,不仅不同时间点击的烟花节奏一致,而且播放时还会出现乱码。那我们一定要用gif图片来实现,可不可以?能。由于同一个gif图片浏览器只会保存一次播放进度,所以不同时间开始的gif图片都是第一次播放的进度。那么我们只需要将这张烟花gif做成多张gif就可以了。exportclassItemextendsComponent{...render(){return(我要放烟花!
{this.state.fire?{dataList.map((data)=>{return })}
);}}在gif后面加上一个唯一的id,那么每一个item都会是不同的gif,这样每个烟花的播放进度都是单独维护的,不会共享,所以上面的问题就解决了。但是又出现了一个问题,因为添加了id,如果列表中有10个单项,就会加载10个fire.png,所以如果是这种情况,我不建议大家使用gif图片来实现。2.动画相信大家都用过@keyframe和animation来实现动画。这个功能非常强大,可以实现最简单的动画需求。那我们还是用烟花的例子来分析。由于gif图有多次播放进度共享的问题,用动画切换background-position可以吗?是的,我们让设计者把烟花导出到一个序列帧,我们用step来移动背景,就可以播放动画$frame:20;$ratio:100%/$frame;@keyframesplaying{@for$ifrom0到$frame{#{$i*$ratio}{background-position-x:-88px*$i;}}100%{背景位置x:0;}}.fire{宽度:88px;高度:88px;背景:fire.png;背景尺寸:88px;&.play{animation:playing1500msstep-end}}是不是很简单!不!这里还是有坑的!大家想一想,sequencediagram和background-position是同方向变化还是不同方向变化?(ps:时序图是从左到右,background-position-x的变化是同一个方向,background-position-y的变化是不同的方向)答案是方向不同,没问题.刚开始接触一个需求,我们用上面的方法实现的时候,郁闷的发现动画播放的时候,在某些机型上会左右晃动。立马知道是因为编译转成rem单位,导致机器有些宽度。模型上rem转px时有个无敌小数点权衡,导致上一帧向左平移1px,下一帧向右平移1px。所以我的第一个想法是不让编译器帮忙转成rem,但是如果我这样做了,不同的模型就不能适配了。后来尝试把序列帧的方向改成竖直的,惊奇的发现没有抖动了。突然一道闪电闪过,想通了,原来是background-size出了问题。因为我们的序列帧图片比较长,所以需要把background-size设置为图片大小,然后改变background-position-x来实现动画。由于我将序列帧更改为垂直排列$frame:20;$ratio:100%/$frame;@keyframesplaying{@for$ifrom0to$frame{#{$i*$ratio}{//vertical改变位置background-position-y:-88px*$i;}}100%{背景位置-y:0;}}.fire{宽度:88px;高度:88px;背景:fire.png;背景大小:100%;&.play{animation:playing1500msstep-end}}那么我们此时锁定图片的宽度,改变垂直位置,问题就解决了。3.AE导出骨骼动画/ae导出画布当动画很复杂的时候,比如我们要实现一头猪走路,我们需要在猪不走的时候停止摇头,让他的头在不走的时候摇猪站起来走路。使用sequenceframe来使用上面的动画也是可以实现的,但是毕竟sequenceframe图片比较大,但是有没有更节省资源的方式呢?设计师可以用ae导出一只狗的各个部位的动画,即猪的头/身体/四肢/尾巴都是拆解材质,将这些部位分别进行旋转/位移/缩放,组合在一起完成一头猪。这种方法基本上是拿设计师的素材进行修复,动画效果很好。缺点是不能使用transform可以实现的效果以外的效果,比如变形。ae导出画布需要配合lottie库使用,工作量也由设计者承担。