画布图案偏移

kan*_*gax 7 html5 canvas

我正在尝试修改画布模式的起源,但无法达到我想要的效果.

我需要绘制一条填充了虚线图案的线条.通过createPattern(动态创建画布元素)创建虚线图案.

画布(基本上是一个红点)的创建方式如下:

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, dotWidth / 2, 0, Math.PI * 2, false);
  patternCtx.closePath();
  patternCtx.fill();

  return patternCanvas;
}
Run Code Online (Sandbox Code Playgroud)

然后使用该模式(画布)绘制一条线:

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();
Run Code Online (Sandbox Code Playgroud)

所以我们得到这个:

在此输入图像描述

现在,我想用10px来抵消这些点的来源.翻译模式画布没有帮助,因为我们没有获得完整的点:

在此输入图像描述

并且翻译画布本身的上下文并没有帮助,因为它抵消了线,而不是模式本身:

在此输入图像描述

翻译上下文似乎不会影响模式起源.

有没有办法修改模式本身的偏移量?

小智 10

更新由于这个答案被张贴现在有(自2015/02)本地setTransform()CanvasPattern实例本身(见规格).它可能还没有在所有浏览器中可用(只有Firefox在编写时支持它).

方法1

您可以偏移主画布并将增量值添加到该行的实际位置:

var offsetX = 10, offsetY = 10;
ctx.translate(offsetX, offsetY);
ctx.lineTo(x - offsetX, y - offsetY);
// ...
Run Code Online (Sandbox Code Playgroud)

(演示只显示正在翻译的模式,但当然,通常你会将它与它一起移动).

线

这样你取消了本身的翻译.但它引入了一些开销,因为除非您可以缓存结果值,否则每次都需要计算坐标.

方法2

我能想到的另一种方式是创建一种自我模式.即,对于图案画布重复点,以便当您将其移动到其边界之外时,它将以相反的方向重复.

例如,这里第一个正方形是正常图案,第二个是描述为方法二的偏移图案,第三个图像使用偏移图案进行填充,表明它将起作用.

关键是两个模式具有相同的大小,并且第一个模式重复偏移到第二个版本中.然后可以将第二个版本用作主要的填充.

例2

示例3动画

点

var ctx = demo.getContext('2d'),
    pattern;

// create the pattern    
ctx.fillStyle = 'red';
ctx.arc(25, 25, 22, 0, 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, 0, 200, 200);
Run Code Online (Sandbox Code Playgroud)


Sha*_*aez 6

您可以在绘制线条/形状之后以及在描边/填充之前简单地翻译上下文以偏移图案.更新小提琴http://jsfiddle.net/28BSH/27/

ctx.fillStyle = somePattern;
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(180, 180);
ctx.save();
ctx.translate(offset, offset);
ctx.stroke();
ctx.restore();
Run Code Online (Sandbox Code Playgroud)