使用 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应用还是比较困难的一件事情!

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

思路

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

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)

作者:许凡

时间: 2016-01-22

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

HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

原文:HTML5 canvas绘制雪花飘落动画(需求分析.知识点.程序编写分布详解) 看到网上很多展示html5雪花飞动的效果,确实非常引人入胜,我相信大家也跟我一样看着心动的同时,也很好奇,想研究下代码如何实现:虽然哦很多地方也能下载这些源码,不过也不知道别人制作此类动画时的思路及难点分析. 我这几天刚好学习了一下,也趁着此刻有时间从需求分析.知识点.程序编写一步步给大家解剖下,要是在各位关公面前耍大刀了,可别见笑哟. 最终效果图如下: 图1 一.需求分析 1.圆形雪花 本示例中雪花形状使用圆

html5 canvas全屏烟花动画特效

许多地方在春节.元宵等节日有放烟花的习俗,如果在网页上模拟烟花,以前也有一些javascript实现的效果,自从HTML5兴起之后,网页模拟烟花更加容易.逼真了. 效果展示:http://hovertree.com/texiao/html5/43/ 效果图: 代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta htt

HTML5 Canvas draw方法制作动画效果示例

HTML5 Canvas动画效果演示 主要思想: 首先要准备一张有连续帧的图片,然后利用HTML5 Canvas的draw方法在不同的时间间隔绘制不同的帧,这样看起来就像动画在播放. 关键技术点: JavaScript 函数setTimeout()有两个参数,第一个是参数可以传递一个JavaScript方法, 另外一个参数代表间隔时间,单位为毫秒数.代码示例: setTimeout( update, 1000/30); Canvas的API-drawImage()方法,需要指定全部9个参数: c

8个经典炫酷的HTML5 Canvas动画欣赏

HTML5非常强大,尤其是Canvas技术的应用,让HTML5几乎可以完成所有Flash能完成的效果.本文精选了8个经典炫酷的HTML5 Canvas动画欣赏,每一个都提供全部的源代码,希望对你有所帮助. 1.HTML5 Canvas可拖动的弹性大树摇摆动画 今天让我们继续来分享一个炫酷的HTML5动画,它是一款基于HTML5 Canvas的大树摇摆动画,这款HTML5动画的特点是我们可以拖拽树枝,从而让整棵树摇摆起来,这样就真实地模拟了大树从摇摆到静止的整个过程,相当逼真. 在线演示     

《HTML5 canvas开发详解(第2版)》——第1章 HTML5 Canvas简介1.1 什么是HTML5

第1章 HTML5 Canvas简介 HTML5是新一代的HTML,即超文本标记语言.HTML从1993年第一次标准化后,便奠定了万维网的基础.HTML通过使用将标签用尖括号(< >)括起来的方式定义Web页面内容. HTML5 Canvas是屏幕上的一个由JavaScript控制的即时模式位图区域.即时模式是指在画布上呈现像素的方式,HTML Canvas通过JavaScript调用Canvas API,在每一帧中完全重绘屏幕上的位图.作为一名程序员,所要做的就是在每一帧渲染之前设置屏幕的显

《HTML5 Canvas开发详解》——第1章 HTML5 Canvas简介1.1 基础的HTML页面

第1章 HTML5 Canvas简介 HTML5是新一代的HTML,即超文本标记语言.HTML从1993年第一次标准化后,便奠定了万维网的基础.HTML通过使用将标签用尖括号(< >)括起来的方式定义Web页面内容. HTML5 Canvas是屏幕上的一个由JavaScript控制的即时模式位图区域.即时模式是指在画布上呈现像素的方式,HTML Canvas通过JavaScript调用Canvas API,在每一帧完全重绘屏幕上的位图.作为一个程序员,所要做的就是在每一帧渲染之前设置屏幕显示,

canvas-Html5 Canvas通过鼠标移动画圆,一下为Javascript画圆部分函数 有什么问题?

问题描述 Html5 Canvas通过鼠标移动画圆,一下为Javascript画圆部分函数 有什么问题? var canvas=document.getElementById("demo"); var cxt=canvas.getContext("2d"); function circle() { canvas.onmousedown=function(evt) { cxt.lineWidth=1; evt=window.event||evt; var startX

html5游戏开发-关于html5 canvas 绘图动画的问题,我要实现把一张图片绘制在canvas中,然后使其动起来

问题描述 关于html5 canvas 绘图动画的问题,我要实现把一张图片绘制在canvas中,然后使其动起来 情况说明: 图像可以绘制,但是使用setInterval以后就一闪而过,然后没有图像;了 <!doctype html> 我的图片 // 设置绘图环境 var myMap = document.getElementById("Map"); var cxt=myMap.getContext('2d'); // 设置图像位置初始位置的变量 var x=20; var

html5 利用canvas实现超级玛丽简单动画

最近在学习html5,其中涉及到很关键的元素canvas-画布,在网上下载了一些游戏源代码,虽然能看懂,但是想单独地针对某个功能提取出来还是有难处的,于是乎自己又上网查找了一些例子,才将超级玛丽简单的动画给实现了. 设计中涉及到的主要的drawImage()函数 (1)drawImage(image,x,y)该方式是最基本的操作方式,具体是指将你整个要操作的图像对象描绘 在指定的坐标轴上,左上角为(0,0)原点,以此计算你想要它描绘的位置 (2)drawImage(image,x,y,width