Android 4+ html5画布不重绘
Posted
技术标签:
【中文标题】Android 4+ html5画布不重绘【英文标题】:Android 4+ html5 canvas not redrawing 【发布时间】:2012-09-30 01:27:09 【问题描述】:我目前正在使用 phonegap 开发一个 android 应用程序。我有一个 html5 画布,我在上面绘制和动画对象。它在 android 2.3 上运行良好,但在 android 4+ 上它不会重绘画布。我尝试将 kinetic.js 和 easel.js/tween.js 用于我的动画,并且这两个库都出现了不清除画布的问题。我在画布上显示和隐藏 div 时取得了一些成功,但它并不总是有效。我只能假设这是一个 android 4+ 特定的错误或某种类型的功能,以增强 html5 画布性能。
有谁知道是否有一些我可以更改的设置或我可以在 android 4 或 javascript 中调用的方法,这将允许我在动画期间强制重绘我的 html5 画布?
还应注意,动画似乎可以在 4.1 google api 模拟器中使用 easel.js/tween.js(画布清除并重绘),但不适用于运行 4.1.1 的手机。
我对正在发生的事情做了一些进一步的研究。从本质上讲,动画一开始的形状似乎留下了一个工件,而 clearRect 并没有清除它。我有一个大圆圈,我正在缩小到一个小圆圈。动画仍然发生,但大圆圈不受在画布上调用 clearRect 的影响。
【问题讨论】:
所以我想出了一个解决办法。我仍然不知道根本原因或为什么它只发生在 Android 4+ 中。如果我在第一次绘制到画布之前先设置一个 setTimeout。它不再留下文物。 【参考方案1】:我也没有解决根本问题的方法,但我想出了另一个不完美的解决方法,它不会给您的代码添加延迟。首先在画布上绘制一个虚拟对象。然后绘制您的动画对象(或可拖动对象。因为它也发生在拖动时)。似乎第一个绘制的对象是持久的(即无法正确清除)。使用 KineticJs,我执行以下操作... 1.) 创建舞台,2.) 绘制对象(如舞台大小的矩形作为背景。注意对象不能是透明的),3.)将图层添加到舞台,然后 4.) 运行 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>
【讨论】:
【参考方案2】:我今天在 Android 4.1.1 上遇到了同样的问题,只是我的问题更令人讨厌。我尝试了其他答案中建议的setTimeout
和“绘制虚拟对象”解决方法,但问题仍然存在。经过更多的尝试和错误,我发现如果我在前几帧(前两帧对我来说足够)绘制虚拟对象,之后可以成功清除画布。
另一个相关问题是,如果我在画布顶部显示一个弹出框,然后将其关闭,画布清除错误将再次发生。而这一次画几帧的虚拟对象不再起作用了,对我有用的是先调整画布的大小,然后再绘制几帧的虚拟对象。
显然,这些都是丑陋的解决方法,但可能对遇到相同问题的其他人有用。
【讨论】:
哇,感谢您发布此信息。在我的情况下,我正在为图像制作动画,并且在动画运行几帧后设置图像可以防止“重影”问题。【参考方案3】: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);
;
);
像魅力一样工作
【讨论】:
以上是关于Android 4+ html5画布不重绘的主要内容,如果未能解决你的问题,请参考以下文章