Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么HTML5 Canvas rect/fillRect具有来自画布原点的模式渲染?_Javascript_Html_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 为什么HTML5 Canvas rect/fillRect具有来自画布原点的模式渲染?

Javascript 为什么HTML5 Canvas rect/fillRect具有来自画布原点的模式渲染?,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我最近在画布上玩一些代码时发现了这个奇怪之处 给定以下代码 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

我最近在画布上玩一些代码时发现了这个奇怪之处

给定以下代码

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);
我已经在上设置了一个演示来说明这个问题。只需更改x和y偏移以查看默认情况,然后使用复选框启用转换以“修复”问题

所以我的问题是:


当填充模式时,为什么
rect
fillRect
的行为是这样的呢?考虑到大多数情况下,它是违反直觉的?

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

此外,您已经有可能让模式在另一个点开始,因此实际上不需要在该函数中提供更多功能

在这里:您还将找到一个函数,它可以为您做任何事情。

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

由于图案没有“意识到”它是否被使用,并且如果它仅用于样式,也没有与使用其位置的方法绑定,那么坐标系将成为唯一的定位点,可以说是绘制和平铺图案的位置

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

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

ctx.fillStyle = myPattern;
ctx.rect(x1, y1, w, h);
ctx.rect(x2, y2, w, h);
ctx.fill();
两个rect中的哪一个应该作为填充操作的锚点?(fillRect只是rect+fill的缩写,但使用的临时路径不影响当前全局路径)

rect()、arc()等仅创建路径,当您调用fill/stroke时,这些路径将以设置的任何填充/笔划样式栅格化到画布

当调用填充/笔划时,浏览器(或操作系统的图形子系统)可能会执行以下操作:

  • 使用点(比例、方向和位置)的变换矩阵栅格化形状/路径,并创建内部遮罩/蒙版
  • 使用该遮罩/蒙版以当前样式合成(填充)该遮罩
  • …其他步骤
现在只有一个遮罩/蒙版,您不再有任何已定义的定位点,并且只剩下坐标系


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

一般来说,最好总是
翻译
画布,然后在
0,0
处画画,这样生活会轻松得多。