【问题标题】:Why HTML5 Canvas rect / fillRect with pattern renders from canvas origin?为什么 HTML5 Canvas rect / fillRect 带有图案从画布源呈现?
【发布时间】:2014-10-02 02:10:00
【问题描述】:

我最近在画布上玩一些代码时发现了这个奇怪的地方。

给定以下代码

var pattern = ctx.createPattern(image, 'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(10, 10, 500, 500);

您会期望它会在画布上从点 x:10, y:10 开始渲染带有此图像 的图案。

但实际上似乎发生的是,它呈现从 x:10, y:10 开始的矩形,但模式从 x:0, y:0 开始。

解决方法是翻译画布

ctx.translate(10,10);

然后从x:0, y:0开始渲染矩形

ctx.fillRect(0, 0, 500, 500);

我在jsfiddle 设置了一个演示来说明这个问题。只需更改 x 和 y 偏移量以查看默认情况下会发生什么,然后使用复选框启用翻译以“修复”问题。

所以我的问题是这样的:

为什么rectfillRect 在填充模式时的行为是这样的,考虑到大多数时候它是违反直觉的?

【问题讨论】:

  • 一般来说,最好总是translate 画布然后在0,0 绘图,这让生活sooo 更轻松。

标签: javascript html canvas html5-canvas


【解决方案1】:

模式 (CanvasPattern) 是独立的全局对象(在画布上下文的意义上),不绑定到使用它作为样式的方法。

由于模式没有“意识到”它是否被使用,并且如果它仅用于样式,并且两者都没有绑定到使用它的方法,则 坐标系 变为唯一可以说在哪里绘制和平铺图案的锚点。

例如,执行 rect(x, y, w, h) 只会通知浏览器 您要渲染 矩形本身,而不是 如何填充它,这是样式模式保存的信息,是在下一步合成/填充当前样式(可以是纯色、图案或渐变中的任何一种)时执行的操作后者的行为与模式相似)。

另一个方面是路径可以累积。例如,如果你这样做了:

ctx.fillStyle = myPattern;
ctx.rect(x1, y1, w, h);
ctx.rect(x2, y2, w, h);
ctx.fill();

两个矩形中的哪一个应该作为填充操作的锚点? (fillRect 只是 rect+fill 的简写,但使用的是临时路径,不会影响当前的全局路径)。

rect()、arc() 等仅创建 路径,当您调用填充/描边时,这些路径会以设置的任何填充/描边样式栅格化到画布上。

当调用填充/描边时,浏览器(或操作系统的图形子系统)可能会做这样的事情:

  • 使用点的变换矩阵(比例、方向和位置)栅格化形状/路径并创建内部蒙版/遮罩
  • 使用该蒙版/遮罩以当前样式合成(填充)该蒙版
  • ..其他步骤

现在只有一个蒙版/遮罩,您不再有任何定义的锚点,坐标系是唯一剩下的东西。

(远离使用不同算法的可能性,即多边形填充,路径仍然存在等 - 但性能和图形系统会影响这些决策以及目标是实现跨浏览器和跨浏览器的相同行为的规范跨平台)。我在写这篇文章时半睡半醒,所以我希望我没有让它变得更加模糊......

【讨论】:

    【解决方案2】:

    你是对的,你必须设置一个偏移量才能让模式从你给定的点开始。我认为这是因为大多数时候图案要小得多,并且必须制作壁纸效果,而作为壁纸,中间区域很重要,而不是角落。

    此外,您已经可以让模式从另一个点开始,因此实际上不需要在此函数中添加更多功能。

    在这个:question,你还会发现一个可以为你做所有事情的函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2016-11-05
      • 1970-01-01
      • 2016-08-12
      • 2013-12-15
      • 2015-08-12
      • 1970-01-01
      相关资源
      最近更新 更多