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

时间: 2018-10-18阅读: 1489标签: 动画

背景

过年的项目中遇到一个问题让我百思不得其解,明明我的帧率保持在60帧,为何我的动画却一直抖动?

我的场景是一个匀速直线运动的小姐姐。

先上一个 Demo

在这个 Demo 中,小姐姐是按照 x 轴 10px/s,y 轴 30 px/s 进行移动的,不过她的移动是明显伴随着抖动的。

这到底是怎么了呢?


解决

如果小姐姐的y轴速度是 10px/s,我们的帧率是 60f/s,计算一下:

10 / 60 = 1/6 (px/f)

实际上,的实际速度是每 6 帧才会移动 1px,这当然会有抖动,小姐姐走一步停一会,总感觉怪怪的~

我索性把小姐姐的移动速度调快,调成 100px/s,发现,还是会抖动,以为高高兴兴能解决了这个问题,发现还是没那么简单。

既然我们能算,那我们就算一算

100 / 60 = 10/6 (px/f) = 1.666666....(px/f)

写了个for循环,看看一秒中每一帧小姐姐都在什么位置

for(let i = 0; i < 60; i ++) {
  console.log(i*10/6)
}

输出结果取小数点后两位是这样的:

0.00 1.67 3.33 5.00 6.67 8.33 10.00 11.67 13.33 15.00 16.67 18.33 20.00 21.67 23.33 25.00 26.67 28.33 30.00 31.67
33.33 35.00 36.67 38.33 40.00 41.67 43.33 45.00 46.67 48.33 50.00 51.67 53.33 55.00 56.67 58.33 60.00 61.67 63.33
65.00 66.67 68.33 70.00 71.67 73.33 75.00 76.67 78.33 80.00 81.67 83.33 85.00 86.67 88.33 90.00 91.67 93.33 95.00 96.67 98.33

那么作为浮点数,Canvas 将如何定位呢?

我们来写一个 Demo

使用 Chrome 打开,作为一个像素眼,我发现,小姐姐定位在 50.6px 的时候,其实就已经被渲染到 51px 的位置。

所以在 Chrome 中,drawImage中设置的位置最终会被四舍五入,这可能和 css Sub-pixel 有关 这里先不探究。

所以真正的位置其实是

 0 2 3 5 7 8 10 12 13 15 17 18 20 22 23 25 27 28 30 32
 33 35 37 38 40 42 43 45 47 48 50 52 53 55 57 58 60 62 63 65
 67 68 70 72 73 75 77 78 80 82 83 85 87 88 90 92 93 95 97 98

从数值来看,每帧移动的距离可能是 1px 也可能是 2px,小姐姐可能是在边跳芭蕾边走路喽~

既然这样,60 帧的帧率下,设置 60px/s 就可以解决问题了,尝试了一下,真的可以!


总结

前端动画/游戏开发 requestAnimationFrame 之 锁帧 这篇文章介绍过,在项目中我们可能对动画进行锁帧,帧率可能是 60 或者 30,如果我们想保证渲染不抖动,在匀速直线运动中,我们尽量保证我们设置的速度要是帧率的倍数,或者保证平均每帧移动的像素点是一样的。

在 drawImage 中,不建议使用浮点数进行定位。


来源:https://fanmingfei.com/posts/Why_The_Canvas_Is_Shake.html


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/1163

css3贝塞尔曲线(cubic-bezier)

css3 animation模块,其中animation-timing-function 和 transition-timing-function两个属性来控制动画速度分别提供了ease,liner,ease-in,ease-out

两张图解释CSS动画的性能

在手机上使用CSS动画时很多时候会感到卡顿,然后网上很多教程说开启GPU加速 transform: translate3d(0,0,0); 可解决,但是为什么开启GPU加速就能让动画顺滑呢?

CSS3动画与JS动画的优缺点?

如果动画只是简单的状态切换,不需要中间过程控制,在这种情况下,CSS3动画是优先选择方案。它可以让你将动画逻辑放在样式文件里面,而不会让你的页面充斥JS库。然而如果你在设计很复杂的富客户端界面或者开发一个有着复杂UI状态的APP

CSS3动画:animation

可以让页面中指定的元素按照设定的方式“动”起来,运用的是人视觉延迟的原理,连续地在上一张图消失之前插入下一张;1.animation-name对象的动画名称,以便后续设置动画属性时使用默认为none

CSS3动画属性:transform变形

Transform字面上就是变形,改变的意思。在CSS3中transform主要包括以下几种:旋转rotate、扭曲skew、缩放scale和移动translate以及矩阵变形matrix。

Vue 中 JS 动画与 Velocity.js 的结合

前面学习了用css实现动画效果,那 Vue 中能不能用js实现动画效果呢?其实 Vue 提供了很多动画钩子,入场动画钩子函数有before-enter、enter、after-enter,与入场动画对应的出场动画钩子函数有before-leave、leave、after-leave。它们的用法与入场动画用法一样

css @keyframes属性 语法

@keyframes是CSS的一种规则,可以用来定义CSS动画的一个周期的行为,创建简单的动画。作用:通过 @keyframes 规则,您能够创建动画。

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

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

css3中动画有哪些属性?

通过CSS3,我们能够创建动画,这可以在许多网页中取代动画图片、Flash 动画以及 JavaScript。动画是使元素从一种样式逐渐变化为另一种样式的效果。那么在CSS中动画属性有哪些?

Flutter 动画

Flutter动画中有4个比较重要的角色:Animation、Controller、Curve、Tween,先来了解一下这四个角色;Animation是Flutter动画库中的核心类,用于插入指导动画的值

点击更多...

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