CSS3 Animations を適用するとiOSでぼやける

enchant.jsでSpriteやLabelに対してjQueryを使ってエフェクトをかける方法についてはenchant.js + jQuery でエフェクトをつけるに書いた。使い慣れたjavascriptの機能を使ってエフェクトをかけられるのは魅力的だが、Spriteに対してCSS3の機能であるAnimationsを適用すると、iOS(iPhone,iPad等) の Mobile Safariで表示した際に、ピンボケというか過剰なアンチエイリアスというか、ぼやけた感じになってしまった。おかしいな、と思って実験したら、特定の条件下でAnimationsを適用した場合にぼやけてレンダリングされることが分かった。

特定の条件とは、

  • div要素に対してCSSでbackground-imageを適用して画像を表示している(enchant.jsのEntity)
  • 複数の画像にCSS3 Animationsを適用している
  • どれかの要素でCSS3のアニメーションが継続中

といった場合だ。そこで、実験をしてみた。
※結論だけ知りたい人はこちらをクリック

実験

実験用に256×256ピクセルの画像を用意した。
テスト用画像

jQueryを使ってCSSを適用するため、jQueryと「enchant.js + jQuery でエフェクトをつける」で使ったenchant.prototype.jsは既に読み込み済みのものとする。

パターン1.拡大から縮小

以下のCSSとJavaScriptを用意して、test.pngが2倍から1倍に縮小されるプログラムを組んだ。

CSS

@-webkit-keyframes 'myanime' {
	0% {-webkit-transform: scale(2.0); }
	100% {-webkit-transform: scale(1.0); }
}

javascript

var test = new Sprite(256,256);
test.moveTo(320/2-256/2, 480/2-256/2);
test.image = game.assets['test.png'];
$(test.element()).css('-webkit-animation-name', 'myanime');
$(test.element()).css('-webkit-animation-duration', '1s');
$(test.element()).css('-webkit-animation-iteration-count', '1');
scene.addChild(test);

結果


綺麗な画像が表示される。

パターン2.無限アニメする画像を1枚追加してみる

以下のCSSとJavaScriptを用意して、パターン1で表示した画像の下に、ずっと回転しつづける画像(-webkit-animation-iteration-countにinfiniteを指定したdiv要素)を表示してみる。

CSS

@-webkit-keyframes 'myanime' {
	0% {-webkit-transform: scale(2.0); }
	100% {-webkit-transform: scale(1.0); }
}
@-webkit-keyframes 'myrotation' {
	0% { -webkit-transform: rotate(0deg); }
	100% { -webkit-transform: rotate(360deg); }
}

javascript

var foo = new Sprite(256,256);
foo.moveTo(320/2-256/2, 480/2-256/2);
foo.image = game.assets['test.png'];
$(foo.element()).css('-webkit-animation-name', 'myrotation');
$(foo.element()).css('-webkit-animation-duration', '1s');
$(foo.element()).css('-webkit-animation-iteration-count', 'infinite');
scene.addChild(foo);

var test = new Sprite(256,256);
test.moveTo(320/2-256/2, 480/2-256/2);
test.image = game.assets['test.png'];
$(test.element()).css('-webkit-animation-name', 'myanime');
$(test.element()).css('-webkit-animation-duration', '1s');
$(test.element()).css('-webkit-animation-iteration-count', '1');
scene.addChild(test);

結果


画像がぼやける。悲惨。

解決編.

パターン2で手前に表示されていたSpriteのインスタンスtestを、jQueryによって生成されたimg要素に置き換える。

CSS

@-webkit-keyframes 'myanime' {
	0% {-webkit-transform: scale(2.0); }
	100% {-webkit-transform: scale(1.0); }
}
@-webkit-keyframes 'myrotation' {
	0% { -webkit-transform: rotate(0deg); }
	100% { -webkit-transform: rotate(360deg); }
}

javascript

var foo = new Sprite(256,256);
foo.moveTo(320/2-256/2, 480/2-256/2);
foo.image = game.assets['test.png'];
$(foo.element()).css('-webkit-animation-name', 'myrotation');
$(foo.element()).css('-webkit-animation-duration', '1s');
$(foo.element()).css('-webkit-animation-iteration-count', 'infinite');
scene.addChild(foo);

var test = $("").attr({
	src: './resources/test.png'
});
test.css({
	'position': 'absolute',
	'left': (320/2-256/2) + 'px',
	'top': (480/2-256/2) + 'px',
	'-webkit-animation-name': 'myanime',
	'-webkit-animation-duration': '1s',
	'-webkit-animation-iteration-count': '1'
});
$(scene.element()).append(test);

結果


キッチリ、輪郭がクリアな画像が表示された。勝利。

結論としては、背景画像付きのdivにCSS3 Animationsを適用するのではなく、imgに対して適用すればよい。


コメントを残す