背景

本文正在参与「金石计划 . 分割6万现金大奖」

主要在最近的免单突袭活动中,利用了很多的动画特效。 可是有一个 钥匙碎裂的动画特别卡, 一开始对问题的界说是不是页面上的序列帧动画太多,导致canvas 占用了 很多内存,由于播映这个序列帧动画的时候, 测验反应 安卓手机 卡的像幻灯片。可是苹果手机却没事。

原理

咱们先看下 序列帧动画烘托的原理

  1. 第一步是将多张图片转成 一张雪碧图 这儿其实已经确认了 动画的帧数
  1. 然后用 canvas 去烘托 每一帧

咱们看下这张图:

记一次序列帧动画预烘托处理计划

显现 其实也便是 咱们canvas 的容器, 而上面的 1-6 其实便是一张图, 所以序列帧动画的 原理 便是 将1-6 这张图 通过canvas drawImage api 每一帧 进行 截取,然后进行烘托。

外表看是没啥问题, 很简单的逻辑烘托,可是重新制作的进程,实质上是一个不断刮白-重画的进程。但在屏幕上完结这一系列操作是需求必定时间的,并且屏幕上的图形越复杂,所花的时间就越长,咱们肉眼可见的刮白-重画操作,在运用进程中就会让就会直接感觉到屏幕的闪耀。 这就 为啥 在 钥匙爆裂那几张动画卡顿。

记一次序列帧动画预烘托处理计划

为了验证我的猜想, 我将资料中的全体图片运用2x 图 去烘托, 在问题机型表现的卡顿几乎都是没有了,可是 随之带来的一个问题便是图片的质量 就不是很高。 这种关于开发而言, 便是要设计退让,说图片太大。可是这种关于用户体会来说,就不太好。 所以就有了目前调研的预烘托 canvas , 其实 便是在烘托之前 将这些 canvas 烘托好

双缓存画布

现在咱们有一幅图需求放在Canvas中,运用drawImage()办法,有三种写法:

// 将image放到方针canvas指定方位
void ctx.drawImage(image, dx, dy); 
// 将image放到方针canvas指定方位,指定宽高烘托
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
// 将image裁剪之后放到方针canvas指定方位,指定宽高烘托
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

第一种办法仅仅把图片原样放到Canvas中,第二种办法指定宽高就意味着扩大或许缩小图片后再放进去,第三种是将图片裁剪后再扩大或许缩小放到canvas中,这三种写法操复杂度作顺次增加,性能开销也随之增大。

而假如运用离屏烘托(即咱们所说的双缓存画布),咱们能够预先把图片裁剪成想要的尺度,然后将该内容保存起来,制作的时候直接运用第一种写法直接将图片放入Canvas中。

// 在离屏 canvas 上制作var offscreencanvas = document.createElement('canvas');// 宽高赋值为想要的图片尺度
offscreencanvas.width = dWidth;
offscreencanvas.height = dHeight;// 裁剪
offscreencanvas.getContext('2d').drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);// 在视图canvas中制作
viewcontext.drawImage(canvas, x, y);

双缓存画布技能的中心在于体系需求在内存中拓荒一块与当时画面等大的“逻辑屏幕“。咱们的画图和动画操作都会先作用于这块”逻辑屏幕“中,当一个操作在这块”逻辑屏幕“上完结之后,再把整块”逻辑屏幕“投进到咱们的屏幕上。

测验

咱们先看下没有运用预烘托的 canvas 3x 图

记一次序列帧动画预烘托处理计划

很显着在爆裂的这几幁动画,会卡顿, 如同便是卡住了 相同。

运用了 预烘托之后咱们看下 播映的视频

记一次序列帧动画预烘托处理计划

背面的 原理 其实很简单 看下这张图:

记一次序列帧动画预烘托处理计划

咱们提前做好所有序列帧的在方针canvas 的切开, 在这样的进程之下,咱们是无法看到整个图形在屏幕上的重绘进程,从而处理了闪耀问题。就如同看动漫相同,不必双缓存技能,便是画一帧看一帧,肯定会卡顿。而用了双缓存技能,会事先把每一帧画好,不断翻动展示出来。这儿咱们能够联想到 react 的双缓存 fiber 树哦, 就能理解了。

存在的问题

预烘托canvas 存在的问题有下面两个

  1. 第一个是 在 ios 端 对canvas 的内存 有限制,假如序列帧的动画过多, 导致canvas 拿不到上下文
  2. 第二个便是 创立canvas 的js 执行时间 比较久, 在 安卓低端机 表现非常显着
  3. 关于问题的改进战略 下一篇文章再去讲,留点悬念, 能够关注一波

未来展望

Webgl 烘托

这不必定是一种最好的计划,可是关于不借助 webgl 能力是一种优化手段, 假如后边还是对序列帧动画进行晋级, 便是 根据webgl 去烘托每一帧的图片 ,这儿能够参阅pixi 烘托精灵图, 或许图集

pixijs.huashengweilai.com/guide/start…

关于雪碧图的 图片存储, 假如高效的烘托 。。。 我觉都是后边能够优化的方向

资源的预加载计划

关于资源超过几M 的图片计划, 假如不加loading页, 咱们该怎么让用户无感知,体会咱们的游戏。 这些都是咱们能够考虑晋级的。