为什么在移动浏览器上使用<canvas>旋转时会出现条纹?

10

我正在执行对2D画布的旋转,这在桌面上工作得非常好,但在移动端有一个小问题。下面是一个放大的截图:

enter image description here

缩略图图像在500毫秒内旋转约0.2弧度。我认为所有相关的代码都嵌入在下面。正如你所看到的,每个图像顶部角落留下了某种“痕迹”。

var duration = 500;
var start = 0;
var stop = 0.287554326;
var step = (stop - start) / 10;
var steps = (stop - start) / step;
var current = 0;
var delay = duration / steps;
var first = true;
if (navigator.userAgent.match(/iP(hone|[ao]d)|android/i)) step *= 1.5;
var rotate_int = setInterval(function() {
  if (current >= stop) {
    clearInterval(rotate_int);
    callback && callback();
    return;
  }
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  ctx.translate(cvs.width / 2, cvs.height / 2);
  ctx.rotate(step);
  current += step;
  ctx.translate(cvs.width / -2, cvs.height / -2);
  ctx.drawImage(i, 0, 0);
  if (first) {
    first = false;
    thumb.hide();
  }
}, delay);

注释:

  1. 该代码在桌面端表现非常好(最新版本的Firefox,Chrome,Safari,Opera甚至IE)
  2. 我已经测试了以下设备和浏览器:
    1. iPhone 3GS: Safari, Opera Mini
    2. iPhone 4S: Safari
    3. iPad (1st gen): Safari
    4. Android Galaxy S (with gingerbread): default browser, Firefox mobile
    5. Motorola Droid X (with gingerbread): default browser, Firefox mobile
  3. 我没有找到支持<canvas>的桌面浏览器会出现这种情况
  4. 我没有找到任何一个移动设备不会出现这种情况
  5. 发布的图片是从iPad放大的截图
  6. 如果有影响,<canvas>(旋转时)正在通过jQuery进行动画处理,以横跨其后面的图像并停止,这在截图中可见。
  7. 页面上还有第二个<canvas>。它使用相同的大拇指.png,并使用上面发布的相同代码旋转,并且也被动画处理以横跨不同的背景图像(但在相反的方向,即一个"赞"向西北移动,而另一个向东南移动),轨迹也出现在那里,相对于画布上下文的位置相同。
我已经尝试了所有可能的方法,希望能够得出诊断。是否有其他人遇到过类似的情况?我应该尝试什么不同的方法?我是否错过了某个 HTML5 教程网站上的警告标签,警示此类行为?根据 @GGG 的评论,我删除了 UA 嗅探代码(旨在降低画布重绘的数量和频率,因为移动浏览器使用与桌面相同的设置会很卡顿),但这只会导致轨迹更加明显(例如更厚)。然后我尝试重新添加 UA 嗅探代码,但是将循环次数增加了 500%,而不是减少 50%。同样,这导致轨迹变得更加明显。然而,似乎这种加粗是渐近的——换句话说,通过调整动画速度的参数,我可以使轨迹变得更厚,但有一个极限值。
根据 @GGG 的另一条评论,我去编辑图片以添加一些透明数据,试图找到一个合适的解决方法。我看到的是该图片紧贴着画布的顶部和左侧边缘(这是“Photoshop 画布”的边缘,而不是“HTML5 <canvas>”的边缘)。当我在顶部和左侧添加相等的透明数据填充时,条纹问题消失了。以下是原始 PSD 文件(未添加额外间距之前):

enter image description here

所以我的问题是:即使图像(具有非透明像素)填充了其[Photoshop]画布的全部,为什么我的画布上下文clearRect()没有按预期工作?那不应该消除画布范围内的所有内容吗?如果是这样,为什么它会留下这几个像素?
==编辑3==
经过一些研究,发现Cairo被几个主要的渲染引擎(至少是WebKit和Gecko)广泛使用。正如@JonasWielicki最初建议的那样,当Cairo库针对移动执行进行优化时,它是否有点过度热衷?

如果您删除了移动UA嗅探的行,会发生什么? - Dagg Nabbit
@GGG 轨迹变得更加明显(即略微加粗)。 - Chris Tonkinson
1
这对我来说看起来像是一个bug。就好像浏览器在尝试避免不必要的重绘时优化得有点过头了。我建议与任何一个浏览器开发者进行交流。有趣的想法是它发生在所有浏览器上。 - Jonas Schäfer
@JonasWielicki - 有没有参考资料表明所有这些移动浏览器共享一些公共代码?对我来说,无论我使用哪个设备都能获得完全相同的行为,这让我感到不妙。 - Chris Tonkinson
4
@Chris,随意的解决方案想法...如果您在图像的外边缘填充几个透明(或几乎透明)像素会发生什么? - Dagg Nabbit
显示剩余3条评论
1个回答

3
根据评论,尝试在图像边缘添加一些透明像素作为解决方法。
我真的不知道为什么会发生这种情况。我认为这可能与移动设备上alpha通道的奇怪处理有关,但这只是一个猜测。
我注意到移动浏览器似乎在滚动时会丢失或“估计”alpha通道(慢慢向上和向下滚动,甚至字体看起来更加“清晰”)。我想知道它们是否将事物分两个阶段渲染,将alpha通道留给第二阶段,并跳过第二阶段,如果当前“帧”之后立即有另一个“帧”要渲染,那么这是否有意义。也许这会让渲染器以某种方式混淆,在已经绘制了东西的地方认为它没有绘制。
无论如何,这可能确实需要一个错误报告。如果没有其他解释,我很想听听发生了什么。

谢谢!非常好的建议,聪明的解决方法。现在我只需要找到适当的项目来提交错误报告! - Chris Tonkinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接