Android 4+ html5画布没有重绘

时间:2012-10-09 16:48:11

标签: android cordova html5-canvas kineticjs easeljs

我目前正在使用phonegap开发一个Android应用程序。我有一个html5画布,我正在绘制和动画对象。它在android 2.3上运行得很好,但在android 4+上它不重绘画布。我尝试使用kinetic.js和easel.js / tween.js作为我的动画,并且这两个库都没有清除画布的问题。我在画布上显示并隐藏了一个div,但是它不会一直有效。我只能假设这是一个android 4+特定的bug或某种类型的功能来增强html5画布性能。

有没有人知道我是否可以更改某些设置或我可以在android 4或javascript中调用的方法,这将允许我在动画期间强制重绘我的html5画布?

还应该注意的是,动画似乎与4.1 google api模拟器中的easel.js / tween.js一起使用(画布清除和重绘),但不适用于运行4.1.1的手机。

我已经对正在发生的事情做了一些进一步的研究。基本上,似乎动画一开始的形状会留下一个神器,clearRect不会清除。我有一个大圈子,我正缩小到一个小圈子。动画仍然会发生,但是在画布上调用clearRect不会影响大圆圈。

3 个答案:

答案 0 :(得分:7)

我也没有针对root问题的解决方法,但是我提出了另一个不完美的解决方法,它不会给代码增加延迟。首先在画布上绘制一个虚拟对象。然后绘制动画对象(或可拖动的对象。因为它也会在拖动时发生)。似乎第一个绘制的对象是持久的(即无法正确清除)。使用KineticJs,我执行以下操作... 1.)创建舞台,2。)绘制一个对象(就像一个矩形,舞台大小为背景。注意对象不能透明),3。)将图层添加到舞台,然后运行layer.draw()。

之后我可以在画布上绘制任何东西,它在Android中表现正常。 (参见下面的示例。如果没有背景,则在第一次拖动时将对象复制。要测试它,只需将背景的不透明度设置为0)。

一个警告:根据我的经验到目前为止,这发生在任何给定层中的第一个对象上。所以我必须在舞台上调整每一层。根据您的应用程序,它可能会或可能不会比为代码添加时序延迟更好。

这似乎是从Android 4.1.x开始的Android错误。它不会出现在4.0.x中。并且最近升级到本周发出的4.1.2还没有修复。类似的问题与CSS中overflow-x属性的设置有关(参见http://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=35474)。

<script>
  window.onload = function() {
    var stage = new Kinetic.Stage({
      container: "container",
      width: 578,
      height: 200
    });

    var boxLayer = new Kinetic.Layer();
    stage.add(boxLayer);
        var background = new Kinetic.Rect({
          x: rectX,
          y: rectY,
          width: 578,
          height: 200,
          fill: "white",
          stroke: "white",
          strokeWidth: 4,
          draggable: false
        });
    boxLayer.add(background)
    boxLayer.draw();


    var rectX = stage.getWidth() / 2 - 50;
    var rectY = stage.getHeight() / 2 - 25;

    var box = new Kinetic.Rect({
      x: rectX,
      y: rectY,
      width: 100,
      height: 50,
      fill: "#00D2FF",
      stroke: "black",
      strokeWidth: 4,
      draggable: true,
      opacity: 1.0            
    });

    boxLayer.add(box);
    boxLayer.draw();


  };

</script>

答案 1 :(得分:1)

我今天在Android 4.1.1上遇到了同样的问题,只是我的问题更加讨厌。我在其他答案中尝试了setTimeout和“绘制虚拟对象”解决方法,但问题仍然存在。经过更多的试验和错误后,我发现如果我为前几帧绘制虚拟对象(前两帧对我来说足够了),之后可以成功清除画布。

另一个相关的问题是,如果我在画布上显示一个弹出框,然后将其解除,画布清除错误将再次发生。而这次绘制几个虚拟对象的帧不再起作用了,对我来说有用的是先调整画布大小,然后将虚拟对象绘制几帧。

显然这些都是丑陋的解决方法,但对于遇到同样问题的其他人可能会有用。

答案 2 :(得分:1)

function drawImage(imageObj) {
    var stage = new Kinetic.Stage({
        container: "container",
        width: wW,
        height: wH
    }),
    timer = null,
    dummys = 1,
    layer = new Kinetic.Layer();

    timer = setInterval( function() {
        if( dummys >= 2 ) {
            clearInterval(timer);
            layer.clear();
            var darthVaderImg = new Kinetic.Image({
                image: imageObj,
                x: stage.getWidth() / 2 - 200 / 2,
                y: stage.getHeight() / 2 - 137 / 2,
                draggable: true
            });
            layer.add(darthVaderImg);
            stage.add(layer);   
        }else{
            var background = new Kinetic.Rect({
              x: 0,
              y: 0,
              width: wW,
              height: wH,
              fill: "white",
              draggable: false
            });
            layer.add(background)
            layer.draw();
            dummys++;
        }
    }, 10 );

}

var wH = window.innerHeight,
    wW = window.innerWidth,
    mCanvas = document.getElementById('container'),
    imageObj = new Image();

$(document).ready(function(){
    mCanvas.style.width = wW;
    mCanvas.style.height = wH;
    imageObj.src = 'img/darth-vader.jpg';
    imageObj.onload = function() {
        drawImage(this);
    };
});

就像一个魅力