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

简介: ## 背景 过年的项目中遇到一个问题让我百思不得其解,明明我的帧率保持在60帧,为何我的动画却一直抖动? 我的场景是一个匀速直线运动的物体。 先上一个 [Demo](https://codepen.io/fanmingfei/pen/JvYdWW) 在这个 Demo 中,小姐姐是按照 x 轴 10px/s,y 轴 30 px/s 进行移动的,不过她的移动是明显伴随着抖动的。

背景

过年的项目中遇到一个问题让我百思不得其解,明明我的帧率保持在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 1.66 3.33 4.99 6.66 8.33 9.99 11.66 13.33 14.99 16.66 18.33 19.99 21.66 23.33 24.99 26.66 28.33 29.99 31.66
33.33 34.99 36.66 38.33 39.99 41.66 43.33 44.99 46.66 48.33 49.99 51.66 53.33 54.99 56.66 58.33 59.99 61.66 63.33 64.99
66.66 68.33 69.99 71.66 73.33 74.99 76.66 78.33 79.99 81.66 83.33 84.99 86.66 88.33 89.99 91.66 93.33 94.99 96.66 98.33

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

我们来写一个 Demo

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

所以在Chrome中,应该使用了 Banker's rounding 来处理小数的问题。

所以真正的位置其实是

 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,如果我们想保证渲染不抖动,在匀速直线运动中,我们尽量保证我们设置的速度要是帧率的倍数,或者保证平均每帧移动的像素点是一样的。

目录
相关文章
|
4月前
|
前端开发
背景滑动,动感加倍:CSS动画对角线效果全解析!
背景滑动,动感加倍:CSS动画对角线效果全解析!
|
7月前
|
前端开发 JavaScript 搜索推荐
webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)
webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)
152 1
webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)
|
Web App开发 存储 移动开发
用 Canvas 实现一个太阳系动画效果
用 Canvas 实现一个太阳系动画效果
用 Canvas 实现一个太阳系动画效果
|
前端开发 数据可视化
基于canvas的粒子酷炫效果
基于canvas的粒子酷炫效果,可用作可视化大屏的背景展示,即拿即用......
122 0
|
前端开发 JavaScript
canvas中的拖拽、缩放、旋转 (上) —— 数学知识准备
canvas中的拖拽、缩放、旋转 (上) —— 数学知识准备
894 0
canvas中的拖拽、缩放、旋转 (上) —— 数学知识准备
|
前端开发
用canvas绘制一个烟花动画
前言 在我们日常开发中贝塞尔曲线无处不在: svg 中的曲线(支持 2阶、 3阶) canvas 中绘制贝塞尔曲线 几乎所有前端2D或3D图形图表库(echarts,d3,three.js)都会使用到贝塞尔曲线 所以掌握贝塞尔曲线势在必得。这篇文章主要是实战篇,不会介绍和贝塞尔相关的知识, 如果有同学对贝塞尔曲线不是很清楚的话:可以查看我这篇文章——深入理解SVG 绘制贝塞尔曲线 第一步我们先创建ctx, 用ctx 画一个二阶贝塞尔曲线看下。二阶贝塞尔曲线有1个控制点,一个起点,一个终点。 const canvas = document.getElementById( 'canvas'
用canvas绘制一个烟花动画
|
前端开发
巧用 CSS 实现炫彩三角边框动画
巧用 CSS 实现炫彩三角边框动画
204 0
巧用 CSS 实现炫彩三角边框动画
SwiftUI—使用withAnimation制作缩放和渐隐动画
SwiftUI—使用withAnimation制作缩放和渐隐动画
1018 0
SwiftUI—使用withAnimation制作缩放和渐隐动画
|
存储 图形学
动画系统中的基础动画
动画系统中的基础动画
175 0
动画系统中的基础动画