Android CSS spritesheet webkit 转换和动画的问题
我对 HTML5 和 Android 还比较陌生,所以任何建议都很有用。我正在尝试用 HTML5 编写一个简单的游戏,主要针对移动设备。我使用 spritesheets 作为图形,并且“3d”webkit 翻译转换以强制 iOS 设备上的硬件加速。到目前为止,它运行得很好,在 iOS 设备上运行得很好,在 Safari、Firefox 和 Chrome 中也运行得很好。我的问题是 Android 设备上的浏览器(在 HTC Desire 上使用 Android 2.3.3 进行测试) - 我希望它的行为像 Chrome,但显然我错了。 Android 似乎支持 webkit 的东西,但在 3D 翻译和 CSS 动画方面存在问题(即使它们不使用 3D 翻译)。
以下是我尝试将问题归结为核心的内容。 testimage.png 可以是任何东西,但对我来说,它是一个 3*3 网格,显示数字排列如下:
012
345
678
iOS、Chrome 和 Safari 上的输出在垂直线上显示与 0、2 和 3 相对应的纹理部分,其中2 向上和向右动画。在 Android 上,动画“2”(和/或 3d 转换的“1”,如果取消注释代码)显示整个图像,而不是由 _spriteDiv 大小定义的子集,并且在动画发生时显示“3”遇到同样的问题。
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Android Sprite Test</title>
<style>
@-webkit-keyframes testAnim { from { -webkit-transform:translate(32px, 96px) } to { -webkit-transform:translate(256px, 0px) } }
</style>
</head>
<body bgcolor = "#606060">
<script src="./scripts/test.js"></script>
</body>
</html>
JavaScript:
var MakeSprite = function() {
var me = {},
_width = 32,
_height = 32,
_spriteFrame = 1,
_spriteDiv = document.createElement('div'),
_spriteImg = document.createElement('img');
_spriteDiv.id = 'spriteDiv';
_spriteDiv.style.position = 'absolute';
_spriteDiv.style.overflow = 'hidden';
_spriteDiv.style.width = _width + 'px';
_spriteDiv.style.height = _height + 'px';
_spriteImg.id = 'spriteImg';
_spriteImg.src = './testimage.png';
_spriteImg.width = Math.floor(_width * 3);
_spriteImg.height = Math.floor(_height * 3);
_spriteImg.style.position = 'absolute';
_spriteDiv.appendChild(_spriteImg);
document.body.appendChild(_spriteDiv);
me.setFrame = function(n) {
_spriteFrame = n;
_spriteImg.style.left = (-_width * (_spriteFrame % 3)) + 'px';
_spriteImg.style.top = (-_height * Math.floor(_spriteFrame / 3)) + 'px';
};
// Works on iOS, Safari and Chrome - but not Android?
me.translate3d = function(x, y) {
_spriteDiv.style.webkitTransform = 'translate3d(' + x + 'px,' + y + 'px,0px)';
}
// Works on Android, but presumably lacks the hardware acceleration of the 3D version
me.translate2d = function(x, y) {
_spriteDiv.style.webkitTransform = 'translate(' + x + 'px,' + y + 'px)';
}
me.testAnim = function() {
_spriteDiv.style.webkitAnimation = 'testAnim 5s';
}
return me;
};
/////////////////////////////////
// TEST SPRITES
// 2D translate works fine, but is suboptimal
var testSprite = new MakeSprite();
testSprite.translate2d(64, 32);
testSprite.setFrame(0);
// 3D translate doesn't work (it shows the whole image rather than clipping it),
// and it also breaks anything that comes after it
/*
var testSprite2 = new MakeSprite();
testSprite2.translate3d(64, 64);
testSprite2.setFrame(1);
*/
// CSS Animation breaks the sprite in the same way that 3D translation does
// (even though the animation works on a 2D translate), and similarly breaks
// sprites that come after it
var testSprite3 = new MakeSprite();
testSprite3.translate2d(64, 96);
testSprite3.setFrame(2);
testSprite3.testAnim();
// This will look wrong if any preceding sprites use translate3d or testAnim.
var testSprite4 = new MakeSprite();
testSprite4.translate2d(64, 128);
testSprite4.setFrame(3);
有谁知道如何解决这些问题,以便我可以在当前版本的 Android 浏览器上使用 CSS 动画(以及,理想情况下,硬件加速的 webkit 转换)?我听说 Android 的未来版本中对此类事情的支持会减少错误,但说实话,我确实可以做一些适用于当前版本的事情。
I'm relatively new to HTML5 and to Android, so any advice is useful. I'm trying to write a simple game in HTML5, mainly targetting mobile devices. I'm using spritesheets for the graphics, and "3d" webkit translation transforms to force hardware acceleration on iOS devices. It's working pretty well so far, runs pretty well on iOS devices, and also in Safari, Firefox and Chrome. My problem is with the browser on Android devices (testing with Android 2.3.3 on an HTC Desire) - I'd expect it to behave like Chrome, but apparently I'm wrong. It seems that Android supports webkit stuff, but has problems with 3d translate and CSS animations (even if they don't use 3D translates).
The following is my attempt to boil the problem down to its core. testimage.png can be anything, but for me it's a 3*3 grid showing numbers arranged like this:
012
345
678
The output on iOS, Chrome and Safari shows the parts of the texture corresponding to 0, 2 and 3 in a vertical line, with the 2 animating up and right. On Android, the animating "2" (and/or the 3d-transformed "1" if you uncomment the code) displays the whole image rather than the subset defined by the size of _spriteDiv, and whilst the animation is happening the "3" suffers the same problem.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Android Sprite Test</title>
<style>
@-webkit-keyframes testAnim { from { -webkit-transform:translate(32px, 96px) } to { -webkit-transform:translate(256px, 0px) } }
</style>
</head>
<body bgcolor = "#606060">
<script src="./scripts/test.js"></script>
</body>
</html>
JavaScript:
var MakeSprite = function() {
var me = {},
_width = 32,
_height = 32,
_spriteFrame = 1,
_spriteDiv = document.createElement('div'),
_spriteImg = document.createElement('img');
_spriteDiv.id = 'spriteDiv';
_spriteDiv.style.position = 'absolute';
_spriteDiv.style.overflow = 'hidden';
_spriteDiv.style.width = _width + 'px';
_spriteDiv.style.height = _height + 'px';
_spriteImg.id = 'spriteImg';
_spriteImg.src = './testimage.png';
_spriteImg.width = Math.floor(_width * 3);
_spriteImg.height = Math.floor(_height * 3);
_spriteImg.style.position = 'absolute';
_spriteDiv.appendChild(_spriteImg);
document.body.appendChild(_spriteDiv);
me.setFrame = function(n) {
_spriteFrame = n;
_spriteImg.style.left = (-_width * (_spriteFrame % 3)) + 'px';
_spriteImg.style.top = (-_height * Math.floor(_spriteFrame / 3)) + 'px';
};
// Works on iOS, Safari and Chrome - but not Android?
me.translate3d = function(x, y) {
_spriteDiv.style.webkitTransform = 'translate3d(' + x + 'px,' + y + 'px,0px)';
}
// Works on Android, but presumably lacks the hardware acceleration of the 3D version
me.translate2d = function(x, y) {
_spriteDiv.style.webkitTransform = 'translate(' + x + 'px,' + y + 'px)';
}
me.testAnim = function() {
_spriteDiv.style.webkitAnimation = 'testAnim 5s';
}
return me;
};
/////////////////////////////////
// TEST SPRITES
// 2D translate works fine, but is suboptimal
var testSprite = new MakeSprite();
testSprite.translate2d(64, 32);
testSprite.setFrame(0);
// 3D translate doesn't work (it shows the whole image rather than clipping it),
// and it also breaks anything that comes after it
/*
var testSprite2 = new MakeSprite();
testSprite2.translate3d(64, 64);
testSprite2.setFrame(1);
*/
// CSS Animation breaks the sprite in the same way that 3D translation does
// (even though the animation works on a 2D translate), and similarly breaks
// sprites that come after it
var testSprite3 = new MakeSprite();
testSprite3.translate2d(64, 96);
testSprite3.setFrame(2);
testSprite3.testAnim();
// This will look wrong if any preceding sprites use translate3d or testAnim.
var testSprite4 = new MakeSprite();
testSprite4.translate2d(64, 128);
testSprite4.setFrame(3);
Does anyone know how I can get round these problems, so I can use CSS animations (and, ideally, hardware-accelerated webkit transform) on current version of the Android browser? I've heard noises about the support for this kind of thing being less buggy in future versions of Android, but to be honest I could really do with something that works on the current versions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我正在研究这个问题,发现了以下内容:http://caniuse.com/transforms3d。显然,任何版本 < 3 不支持 3D 变换,这有点令人失望。
I was looking into this, and I came across the following: http://caniuse.com/transforms3d. Apparently, anything version that's < 3 doesn't support 3D transforms, which is a little disappointing.