我正在尝试修改画布图案的起源,但无法达到我想要的效果.
我需要绘制一条填充点状图案的线条.虚线图案通过createPattern创建(为其动态创建canvas元素).
画布(基本上是一个红点)的创建方式如下:
function getPatternCanvas() {
var dotWidth = 20,dotdistance = 5,patternCanvas = document.createElement('canvas'),patternCtx = patternCanvas.getContext('2d');
patternCanvas.width = patternCanvas.height = dotWidth + dotdistance;
// attempt #1:
// patternCtx.translate(10,10);
patternCtx.fillStyle = 'red';
patternCtx.beginPath();
patternCtx.arc(dotWidth / 2,dotWidth / 2,Math.PI * 2,false);
patternCtx.closePath();
patternCtx.fill();
return patternCanvas;
}
然后使用该模式(画布)绘制一条线:
var canvasEl = document.getElementById('c');
var ctx = canvasEl.getContext('2d');
var pattern = ctx.createPattern(getPatternCanvas(),'repeat');
// attempt #2
// ctx.translate(10,10);
ctx.strokeStyle = pattern;
ctx.linewidth = 30;
ctx.beginPath();
ctx.moveto(0,0);
ctx.lineto(100,100);
ctx.stroke();
所以我们得到这个:
现在,我想用10px来抵消这些点的来源.翻译模式画布没有帮助,因为我们没有获得完整的点:
并且翻译画布本身的上下文并没有帮助,因为它抵消了线条,而不是图案本身:
翻译上下文似乎不会影响模式起源.
有没有办法修改模式本身的偏移量?
解决方法
更新自此答案发布以来,现在(自2015/02起)CanvasPattern实例本身就有一个本地setTransform()(见
specs).它可能还没有在所有浏览器中可用(只有Firefox在编写时支持它).
方法1
您可以偏移主画布并将增量值添加到该行的实际位置:
var offsetX = 10,offsetY = 10; ctx.translate(offsetX,offsetY); ctx.lineto(x - offsetX,y - offsetY); // ...
Example
(演示只显示正在翻译的模式,但当然,通常你会将它与它一起移动).
这样你就取消了这条线本身的翻译.但它引入了一些开销,因为除非您可以缓存结果值,否则每次都需要计算坐标.
方法2
我能想到的另一种方式是创造一种自我模式.即对于图案画布重复点,以便当您将其移动到其边界外时,它将以相反的方向重复.
例如,这里第一个正方形是正常图案,第二个是描述为方法二的偏移图案,第三个图像使用偏移图案进行填充,表明它将起作用.
关键是两个模式具有相同的大小,并且第一个模式重复偏移到第二个版本中.然后可以将第二个版本用作主要的填充.
Example 2
Example 3 animated
var ctx = demo.getContext('2d'),pattern;
// create the pattern
ctx.fillStyle = 'red';
ctx.arc(25,25,22,2*Math.PI);
ctx.fill();
// offset and repeat first pattern to base for second pattern
ctx = demo2.getContext('2d');
pattern = ctx.createPattern(demo,'repeat');
ctx.translate(25,25);
ctx.fillStyle = pattern;
ctx.fillRect(-25,-25,50,50);
// use second pattern to fill main canvas
ctx = demo3.getContext('2d');
pattern = ctx.createPattern(demo2,'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(0,200,200);