CSS3 animation flicker on Android 2.2 (webkit-transform:translate(..) scale(..) at the same time)
I did some research on Android about CSS3 animation (transformation with webkit-transition). The CSS3 animation is still an experimental feature in Webkit. If you try to do translation and scaling at the same time, you'll find a few glitches and/or bugs in the CSS Animation (for example, see http://www.youtube.com/watch?v=vZdBVzN1B8Y ). In other words, in many versions of Android the property -webkit-transform:matrix(...) does not work correctly. The only correct way to get scaling and translation at the same time is to set "-webkit-transform:scale(...) translate(...)" in this order. I'll shere my results at the bottom of this post.
As you can see in it, I have overcome most of them. However, there's still some `flicker' in some transition on Android 2.2 (Froyo).
Now my question: is there any way to do scaling and translation at the same time without flicker on Android 2.2?
I've also tried -webkit-backface-visibility:hidden;, -webkit-perspective:1000; and -webkit-transform:translate3d(..,0) but these properties introduce some glitch in the transition. You can see it in the following video: http://www.youtube.com/watch?v=Aplk-m8WRUE The scaling is canceled after the transition stops.
Is there any other workaround to suppress flicker? Any ideas?
The below is my results about CSS3 transition on Android (1.5 <= ver <= 2.2). It employs scaling and translation at the same time on the blue box.
<html>
<head>
<title>css3test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width">
</head>
<body>
<div id='log'></div>
<div id='box' style="background-color: blue; width:100; height:100;"></div>
<script language='JavaScript'>
function mesg(str) {
document.getElementById('log').innerHTML = str;
}
var e = document.getElementById('box');
e.style['-webkit-transition-property'] = '-webkit-transform';
e.style['-webkit-transform-origin'] = "0 0";
e.style['-webkit-transition-duration'] = '350ms';
e.style['-webkit-transition-timing-function'] = 'linear';
// These properties will suppress flicker, but spoiles scaling on Android 2.2 ...
// see http://www.youtube.com/watch?v=Aplk-m8WRUE
e.style['-webkit-backface-visibility'] = 'hidden';
e.style['-webkit-perspective'] = '1000';
var b = 0;
function doAnim() {
var trans;
switch(b){
case 0: // step 0. translate and scale at the same time
// 1) matrix
// On Android 1.5, we get no translation, but the box is only enlarged. Broken.
// On Android 2.2, the transition does not occur but the box moves instantly.
//trans = 'matrix(2,0,0,2,100,100)';
// 2) scale first, then translate
// On Androi2.2, there's some glitches.
//trans = 'scale(2,2) translate(50px,50px)';
// 3) tranlate first, then scale -- CORRECT
trans = 'translate(100px,100px) scale(2,2)';
break;
case 1: // step 1. translate
// 1) matrix
//trans = 'matrix(1,0,0,1,35,35)';
// 2) translate only -- will spoil transition --
// On Android 1.5, the transition corrupts and the box repeatedly moves in a wrong direction. Bug?
// see http://www.youtube.com/watch?v=vZdBVzN1B8Y
//trans = 'translate(35px,35px)';
// 3) tranlate first, then scale with (1,1) -- CORRECT
trans = 'translate(35px,35px) scale(1,1)';
break;
case 2: // step 2. scaling
// 1) matrix -- nope.
//trans = 'matrix(1.4,0,0,1开发者_如何学JAVA.4,0,0)';
// 2) scale only -- will spoil transition --
//trans = 'scale(1.4,1.4)';
// 3) tranlate with (0px,0ox), then scale -- CORRECT
trans = 'translate(0px,0px) scale(1.4,1.4)';
break;
case 3: // step 3. again, translate and scale at the same time
// 1) matrix -- nope.
//trans = 'matrix(1.2,0,0,1.2,100,100)';
// 2) scale then translate -- will spoil transition --
//trans = 'scale(1.2,1.2) translate(83.33px,83.33px)';
// 3) tranlate first, then scale -- CORRECT
trans = 'translate(100px,100px) scale(1.2,1.2)';
break;
}
e.style['-webkit-transform'] = trans;
mesg('move '+b+'<br/>transform:'+trans);
b=(b+1)%4;
}
var isAndroid = (new RegExp("android","gi")).test(navigator.appVersion);
if(isAndroid) {
e.addEventListener('touchstart', doAnim, false);
} else {
e.addEventListener('mousedown', doAnim, false);
}
document.addEventListener('touchmove', function(e){ e.preventDefault(); }, false);
</script>
</body>
</html>
it's an open bug. star it to vote for it to be fixed asap.:
http://code.google.com/p/android/issues/detail?id=12451
In most cases the flickering is caused by nested elements who are being animated. Reduce the amount of nested elements, could be hard in some cases, but it helps most of the times.
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
on the parent element might help depending on what youre doing
精彩评论