使用 HTML5 Canvas 实现移动平台动画(游戏)的一些痛点和思路

简介: 前言 最近一直在做一些HTML5 Canvas加速方面的事情,HTML5已经出来相当长一段时间,各浏览器厂商也基本上已经支持!从目前来看,HTML5的大规模普及还是雷声大,雨点小;但从长远来看,HTML5由于其诸多优点,比如本文提到到Canvas元素支持,将会逐渐成为主流,特别是在复杂场景应用中!

前言

最近一直在做一些HTML5 Canvas加速方面的事情,HTML5已经出来相当长一段时间,各浏览器厂商也基本上已经支持!从目前来看,HTML5的大规模普及还是雷声大,雨点小;但从长远来看,HTML5由于其诸多优点,比如本文提到到Canvas元素支持,将会逐渐成为主流,特别是在复杂场景应用中! 本文主要从目前HTML5 Canvas 在实现动画(游戏)中遇到的部分痛点入手,尝试提供一些相应的解决办法和思路!

痛点

  1. 性能问题:目前性能问题HTML5 Canvas的性能问题在Android中表现得尤为突出

  2. 耗电,CPU,内存占用等问题:由于动画,游戏的特殊性,耗电等一直是此类应用中比较突出的问题,并非HTML5 Canvas特有的问题

  3. 品质问题:由于HTML 5是偏Web的一类应用,因此在使用者的固有印象中,一直认为HTML Canvas只能做一些比较初级的动画和游戏,比较复杂的一些游戏,往往就觉得HTML Canvas无法胜任,转而寻求Native的解决方案

  4. 兼容性/适配性问题:这一方面是由于平台造成,比如Android平台的碎片化;另一方面是浏览器的分裂实现,造成同一套标准多个不同版本的不同实现,进而造成开发者要兼顾各种各样的浏览器!

  5. 调试问题:由于移动终端的特殊性,目前在移动终端上调试 JavaScript应用还是比较困难的一件事情!

从不同关注点做一个简单分类:
x

思路

针对上述问题,下面提供了一些方法和思路,可以根据不同的场景和应用做参考:

1. 性能

1). JavaScript 语言层面优化

(1). 设计优化

A. 文字绘制使用缓存Canvas

说明:在动画(游戏)场景中,文字使用一般占比都比较少,但文字的绘制比起图片等来说,其实是最复杂,也最耗时间的!因此大多游戏如果不是出于有文字交互,或动态文字绘制等需求的话,一般会直接使用位图来代替!但也有很多场合需要直接绘制文字,对应于Canvas 的Api主要就是fillText! 在这种情况下,如果直接fillText到显示的Canvas上,会严重降低fps!

方法:创建一个不可见的缓冲Canvas,文字首先绘制到此Canvas上,当需要显示的时候,通过drawImage(canvas...)绘制到显示的Canvas上,这样可有效避免直接调用 fillText 带来的性能降低问题

例子:cocos2d-js,phaser等游戏框架中对文字的处理主要用了此方法

B. 语言层面的设计优化还有很多方式,可以从下面两个链接中找到更多方法:

http://www.cnblogs.com/rhcad/archive/2012/11/17/2774794.html
http://www.cnblogs.com/iamzhanglei/archive/2011/11/29/2267868.html

(2). 工具辅助优化

语言层面不仅可以直接从具体的设计上优化,也可以使用辅助工具来帮助排除js性能瓶颈。

2).Runtime层面优化:

(1). 渲染优化

由于各个平台的实现机制不同,或者同一平台下(比如Android)下各个版本提供的浏览器渲染内核也不尽相同,因此造成HTML5 Canvas在许多情况下渲染性能严重降低!鉴于此,许多直接从Runtime层面来解决性能问题的方案也应运而生!并且取得了不错的效果!比如:

A. 使用GPU硬件加速

方法:直接通过Opengl来实现硬件加速,提高渲染速度,
例子:CocoonJS,Intel XDK等;

2. 耗电

由于动画(游戏)的特殊性,需要不停渲染显示,相对于其他应用来说,会消耗比较多的电量。
目前为止,并没有太多减少耗电量的有效办法。下面的建议可能会有一些帮助:
(1). 在游戏流畅度不受影响的情况下,尽量降低fps, 由于fps越高,渲染越频繁,势必消耗越多的电量;但fps达到60帧/s以后,就已经达到显卡的渲染能力上限,因此过渡提高fps只会增加耗电量;

3. 提高画面品质

(1). 提高平滑度

除了画面的视觉效果外,在动画或游戏中,比较重要的就是画面过渡要流畅,没有生硬感,眼睛不会感觉到刺痛!要改善这些,可以使用下面的方法:

A. 两个画面之间补帧的方式

通过一定的补帧算法(比如 easeIn ,easeOut,透明度变化的)等方式,让前一个画面以微小的变化不停过渡到另一个画面,达到改善过渡的效果!这里比较重要的一点就是在以前的javascript动画实现中,通常通过setTimeout 或setInterval来实现时间控制,推荐使用requestAnimationFrame来控制动画的播放,可以实现比较精确的时间控制,效率较setTimeout高,下面这篇文章给出了一些动画的过渡算法例子

http://www.zhangxinxu.com/wordpress/2013/09/css3-animation-requestanimationframe-tween-动画算法/

(2). 特效:在Runtime支持的情况下,可以使用部分特效效果来提高画面品质,比如3D

4. 兼容性处理

由于浏览器内核分裂和平台碎片化问题(比如Android),导致Api在各个浏览器和Android各个版本下实现不尽一样,比较典型的比如bind在android 某些版本上没有实现,请求动画帧方法requestAnimationFrame在各浏览器内核上的实现不同等。这给开发者带来很大烦恼,要针对不同的平台和浏览器做不同的实现。对于此问题,可以自己根据不同版本做不同的判断来处理,更好的处理版本可以使用一种叫做polyfills的方法,通过这种方式,可以不用担心自己所使用的api在不同的平台上找不到。polyfills这个术语比较拗口,详细可以看一看下面这篇文章,对polyfills做了比较全面的总结!
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills

下面是一个针对requestAnimationFrame和bind的polyfill实现例子:

// Function.bind
// source: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

// window.requestAnimationFrame
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

5. 调试

目前在移动平台上调试javascript相对PC环境来说,相对比较麻烦,下文总结了目前可以使用的一些调试方式,可以参考:
http://blog.csdn.net/alexwang1983/article/details/16882163

该文章来自于阿里巴巴技术协会(ATA

作者:许凡

目录
相关文章
|
1月前
|
移动开发 HTML5
html5掷骰子跳棋游戏源码
html5掷骰子跳棋游戏源码
37 1
html5掷骰子跳棋游戏源码
|
2月前
|
前端开发 JavaScript API
2024 新年HTML5+Canvas制作3D烟花特效(附源码)
2024 新年HTML5+Canvas制作3D烟花特效(附源码)
50 0
|
2月前
|
存储 移动开发 前端开发
HTML新特性【HTML5内联SVG、SVG_矩形、SVG 与 Canvas两者间的区别 、HTML5_MathML 】(三)-全面详解(学习总结---从入门到深化)
HTML新特性【HTML5内联SVG、SVG_矩形、SVG 与 Canvas两者间的区别 、HTML5_MathML 】(三)-全面详解(学习总结---从入门到深化)
46 0
|
1月前
|
前端开发 JavaScript 容器
编程笔记 html5&css&js 032 HTML Canvas
编程笔记 html5&css&js 032 HTML Canvas
|
2月前
|
安全 Windows
在线网页版扫雷游戏HTML源码
在线网页版扫雷游戏HTML源码
53 1
在线网页版扫雷游戏HTML源码
|
2月前
|
前端开发 JavaScript API
【HTML】SVG实现炫酷的描边动画
今天闲来无事,看到Antfu大佬的个性签名,觉得还是非常炫酷的,于是也想要搞一个自己的个性签名用来装饰自己的门面,不过由于手写的签名太丑了,遂放弃。于是尝试理解原理,深入研究此等密法,终于小有所成,发现原来是描边动画,于是记载如下,方便日后借鉴。
44 3
|
3月前
|
移动开发 前端开发 JavaScript
html5 Canvas 绘制基本图形 从直线图形到使用路径 - 直线、矩形、路径、多边形、复杂组合图形
html5 Canvas 绘制基本图形 从直线图形到使用路径 - 直线、矩形、路径、多边形、复杂组合图形
127 0
html5 Canvas 绘制基本图形 从直线图形到使用路径 - 直线、矩形、路径、多边形、复杂组合图形
|
3月前
|
JavaScript
基于js和html的骰子游戏
基于js和html的骰子游戏
21 0
|
3月前
|
前端开发 JavaScript
html+css+js开发一个猜数字游戏
【1月更文挑战第5天】html+css+js开发一个猜数字游戏
35 1
|
3月前
|
前端开发 JavaScript 定位技术
web版拳皇,使用html,css,js来制作一款拳皇游戏
web版拳皇,使用html,css,js来制作一款拳皇游戏
35 0