使用 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

作者:许凡

目录
相关文章
|
26天前
|
前端开发 JavaScript
Canvas三维变化背景动画HTML源码
Canvas三维变化背景动画HTML源码
26 5
|
2月前
|
移动开发 JavaScript 数据管理
HTML5 拖放在游戏中的应用
HTML5的拖放功能在游戏开发中广泛应用,尤其在创建交互式网页游戏时。它支持多种场景,如拖动角色或物品、选择和装备物品、拼图或配对游戏以及自定义界面布局。通过简单的HTML和JavaScript代码,可实现流畅的拖放交互,并提供视觉反馈,增强用户体验。此外,还需考虑设备兼容性和数据管理,确保游戏在不同设备和浏览器上都能良好运行。总之,HTML5拖放功能使网页游戏更生动有趣。
|
2月前
|
XML 移动开发 前端开发
HTML5 SVG和canvas的性能探讨
HTML5 中的 SVG(可缩放矢量图形)和 Canvas(画布)分别用于网页图形绘制。SVG 基于矢量图形,使用 XML 描述,适合静态或少量动态内容(如图标、图表),易于编辑且保持高分辨率;Canvas 则基于位图,通过 JavaScript 绘制,更适合快速更新大量图形的场景(如游戏、动态动画),但在复杂图形计算时可能遇到性能瓶颈。总体而言,SVG 适用于静态和少量动态内容,而 Canvas 更适合高频率更新和性能要求高的场景。
|
2月前
|
移动开发 前端开发 JavaScript
HTML5 Canvas详解及应用
HTML5 Canvas 允许通过 JavaScript 在网页上动态绘制图形、动画等视觉内容。首先在 HTML 中定义 `&lt;canvas&gt;` 元素,并通过 JavaScript 获取画布上下文进行绘制。常见方法包括绘制矩形、路径、圆形和文本,以及处理图像和创建动画效果。适用于游戏开发、数据可视化、图像编辑和动态图形展示等多种应用场景。需要注意性能优化、无状态绘制及自行处理事件等问题。
|
2月前
|
C++ Windows
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
|
2月前
|
移动开发 前端开发 数据挖掘
用HTML5中的 画布(Canvas)在“圳品”信息系统网页上绘制显示饼图
用HTML5中的 画布(Canvas)在“圳品”信息系统网页上绘制显示饼图
|
2月前
|
前端开发
在 HTML canvas 绘制文本
在 HTML canvas 绘制文本
20 0
|
3月前
|
移动开发 前端开发 JavaScript