title: CSS3 animation flicker on Android 2.2 (webkit-transform:translate(..) scale(..) at the same time)
body: <p>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 <a href="http://www.youtube.com/watch?v=vZdBVzN1B8Y">http://www.youtube.com/watch?v=vZdBVzN1B8Y</a> ). In other words, in many versions of Android the property <em>-webkit-transform:matrix(...)</em> does not work correctly. The only correct way to get scaling and translation at the same time is to set <em>"-webkit-transform:scale(...) translate(...)"</em> <strong>in this order</strong>.
  I'll shere my results at the bottom of this post.</p>
  
  <p>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).</p>
  
  <p>Now my question: is there any way to do scaling and translation at the same time without flicker on Android 2.2?</p>
  
  <p>I've also tried  <em>-webkit-backface-visibility:hidden;</em>, <em>-webkit-perspective:1000;</em> and <em>-webkit-transform:translate3d(..,0)</em> but these properties introduce some glitch in the transition. You can see it in the following video: <a href="http://www.youtube.com/watch?v=Aplk-m8WRUE">http://www.youtube.com/watch?v=Aplk-m8WRUE</a>
  The scaling is canceled after the transition stops.</p>
  
  <p>Is there any other workaround to suppress flicker?
  Any ideas?</p>
  
  <hr>
  
  <p>The below is my results about CSS3 transition on Android (1.5 &lt;= ver &lt;= 2.2).
  It employs scaling and translation at the same time on the blue box.</p>
  
  <pre><code>&lt;html&gt;
  &lt;head&gt;
   &lt;title&gt;css3test&lt;/title&gt;
   &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;  
   &lt;meta name="viewport" content="width=device-width"&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;div id='log'&gt;&lt;/div&gt;
  &lt;div id='box' style="background-color: blue; width:100; height:100;"&gt;&lt;/div&gt;
  &lt;script language='JavaScript'&gt;
  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.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+'&lt;br/&gt;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);
  &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>