これはCreateJSを使用した際にAndroid4を搭載した一部のスマートフォンで発生する不具合に関する報告である。
概要
CreateJSを使用した際にAndroid4を搭載した一部のスマートフォンで、不具合が発生することがいくつかのブログで報告されている。問題報告と同時に解決策を提示してるブログもある為、それを検証した結果を報告する。
本件に関するブログ
本件に関して触れているブログとして以下のものがある。
(1)まるちゃんブログ
CreateJSでハマったこと
(2)1 pixel|サイバーエージェント公式クリエイターズブログ
Flashで作るスマフォブラウザゲーム向けアニメーション
(3)しょぶろぐ
Android4.0とCanvasアニメーションの話
不具合の起こる端末
実際に不具合の起こる端末として以下の名前が挙げられている。[]内の数字は上記のブログの番号を示すものである。
- Galaxy SⅢ [(1),(3)]
- Xperia GX [(1),(3)]
- Xperia Z [(2)]
不具合の内容
端末と不具合の内容は以下の通りである。[]内の数字は上記のブログの番号を示すものである。
Galaxy SⅢ
- アニメーション途中に表示が崩れる [(1)]
- ブラウザが落ちる [(1)]
- canvasの領域外に描画しようとするとブラックアウトする [(2)]
- 画面がちらついて強制終了する [(3)]
Xperia GX
- アニメーション途中に表示が崩れる [(1)]
- ブラウザが落ちる [(1)]
- 画面がちらついて強制終了する [(3)]
Xperia Z
- canvasアニメーションを再生するのとほぼ同じタイミングでブラウザが落ちる [(2)]
*尚、上記のブラウザが具体的にどのブラウザであるかはいずれのブログでも触れられていない。
不具合の回避方法
不具合の回避方法として以下の方法が取り上げられている。[]内の数字は上記のブログの番号を示すものであり、その後に続く端末名は該当ブログで触れられているものである。
- 一度のclearRect()で更新する領域を小さく抑えておく [(1) : Galaxy SIII,Xperia GX]
- canvas領域以上の大きさでclearRect()する [(2) : Galaxy SIII,Xperia Z]
これ以降は実際に行った検証に関してである。
検証端末
検証に用いた端末は以下の通りである。
・スマートフォン
MEDIAS N-04C
OS : Google Android 2.3.3
対象ブラウザ
- 標準ブラウザ
Xperia Arc SO-01C
OS : Google Android 2.3.4
対象ブラウザ
- 標準ブラウザ
- FireFox
NEC MEDIAS N-04D
OS : Google Android 4.0.4
対象ブラウザ
- 標準ブラウザ(version : 4.0.4-eng.20121130.132313)
- Chrome(version : 18.0.1025469)
XPERIA Z SO-02E
OS : Google Android 4.1.2
対象ブラウザ
- 標準ブラウザ(version : 4.1.2-wj5_rw)
- Chrome(version : 18.0.1025469)
・タブレット
MOTOROLA XOOM TBi11M
OS : Google Android 3.1
対象ブラウザ
- 標準ブラウザ
Chrome- Firefox
Kindle Fire HD
OS : Google Android 4.0
対象ブラウザ
標準ブラウザ- Silk
Nexus7
OS : Google Android 4.2.2
対象ブラウザ
- Chrome
検証用コード
検証用コードは以下の通りである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>sample</title> <script src="easeljs/utils/UID.js"></script> <script src="easeljs/events/EventDispatcher.js"></script> <script src="easeljs/utils/Ticker.js"></script> <script src="easeljs/events/MouseEvent.js"></script> <script src="easeljs/geom/Matrix2D.js"></script> <script src="easeljs/geom/Point.js"></script> <script src="easeljs/geom/Rectangle.js"></script> <script src="easeljs/ui/ButtonHelper.js"></script> <script src="easeljs/display/Shadow.js"></script> <script src="easeljs/display/SpriteSheet.js"></script> <script src="easeljs/display/Graphics.js"></script> <script src="easeljs/display/DisplayObject.js"></script> <script src="easeljs/display/Container.js"></script> <script src="easeljs/display/Stage.js"></script> <script src="easeljs/display/Bitmap.js"></script> <script src="easeljs/display/BitmapAnimation.js"></script> <script src="easeljs/display/Shape.js"></script> <script src="easeljs/display/Text.js"></script> <script src="easeljs/utils/SpriteSheetUtils.js"></script> <script src="easeljs/utils/SpriteSheetBuilder.js"></script> <script src="easeljs/display/DOMElement.js"></script> <script src="easeljs/filters/Filter.js"></script> <script src="easeljs/ui/Touch.js"></script> <script src="easeljs/version.js"></script> <script> var canvas, stage, circle, speedX = 5, speedY = 3, radius = 15; function init() { canvas = document.getElementById("canvas"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; stage = new createjs.Stage(canvas); circle = new createjs.Shape(); var g = circle.graphics; g.beginFill(createjs.Graphics.getRGB(255, 0, 0, 1)); g.drawCircle(0, 0, radius); stage.addChild(circle); circle.x = canvas.width/2; circle.y = canvas.height/2; createjs.Ticker.useRAF = true; createjs.Ticker.setFPS(30); createjs.Ticker.addEventListener("tick", tick); } function tick() { circle.x += speedX; circle.y += speedY; if(circle.x - radius < 0 || circle.x + radius > stage.canvas.width) { speedX *= -1; } if(circle.y - radius < 0 || circle.y + radius > stage.canvas.height) { speedY *= -1; } stage.update(); } </script> </head> <body onload="init()"> <canvas id="canvas" style="background-color: #DDDDDD"></canvas> </body> </html> |
検証方法
以下に示す検証用コードを次の3つの場合において実行し、その結果を検証する。
EaselJSに変更を加える場合は、easeljs/display/Stage.jsの301行目以降のclearメソッドに変更を加えいている。
[1]何も変更を加えない
clearRect()を行っているコードは以下の通りで何も変更をしていない。
1 2 3 4 5 6 |
p.clear = function() { if (!this.canvas) { return; } var ctx = this.canvas.getContext("2d"); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); } |
http://www.mztm.jp/works/createjs/sample_01/index.html
[2]一度のclearRect()で更新する領域を小さく抑えておく
clearRect()メソッドを以下の様に変更する。これにより一度のclearRect()で更新する領域を小さくしている。
なお、clearRectするCanvas領域の大きさは暫定的なもであり、最適化はしていない。
1 2 3 4 5 6 7 8 9 10 11 12 |
p.clear = function() { if (!this.canvas) { return; } var ctx = this.canvas.getContext("2d"); ctx.setTransform(1, 0, 0, 1, 0, 0); var m = (this.canvas.width + 255) >> 8; var n = (this.canvas.height + 255) >> 8; for (var i = 0; i < m; ++i) { for (var j = 0; j < n; ++j) { ctx.clearRect(i << 8, j << 8, 256, 256); } } } |
http://www.mztm.jp/works/createjs/sample_02/index.html
[3]Canvas領域以上の大きさでclearRect()する
clearRect()メソッドを以下の様に変更する。これによりCanvasより大きい領域をclearRect()する。
1 2 3 4 5 6 |
p.clear = function() { if (!this.canvas) { return; } var ctx = this.canvas.getContext("2d"); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, this.canvas.width + 1, this.canvas.height + 1); } |
http://www.mztm.jp/works/createjs/sample_03/index.html
検証結果
XPERIA Z SO-02Eで標準ブラウザを使用して[1]を実行した場合のみ、canvas表示から1秒程度でブラウザが落ちる事が確認できた。[2]、[3]の場合はブラウザが落ちることはない。
XPERIA Z SO-02E以外の端末では、対象ブラウザ、[1][2][3]のコードに関係なくブラウザが落ちることはない。
日本ではシェアの高い機種であり、この解決が無い場合は、CreateJS自体の有効性が疑われる恐れがある。副作用など無ければ、速やかなマージが望まれる。
スマートフォンの出荷台数に関する参考ページ
http://bcnranking.jp/category/subcategory_0010_month.html
http://bcnranking.jp/news/class/index.html?cl=3
2 Comments
canvas をクリアする方法について、clearRect の代わりに canvas.width = canvas.width ではどうでしょうか?処理は clearRect よりも遅いのですが、もしかしたらこの方法でも解決できるのかも?しれないなと思いました。
yomotsu様
コメント頂きありがとうございます。
“canvas.width = canvas.width”は知らなかったのですが、こんな方法があったのですね。参考になります。
clearメソッドを以下の様に変更して、不具合の確認されているXPERIA Z SO-02Eでこの方法を試してみたところ、標準ブラウザが落ちることはありませんでした。
http://www.mztm.jp/works/createjs/sample_04/index.html
貴重な情報を頂きありがとうございます。
canvas.width = canvas.widthに関する参考サイト
HTML5 canvas のパフォーマンスの改善