如何从 canvas 的另一侧显示部分元素

How to show part of element from other side of canvas

如何从另一侧 canvas 显示 canvas 之外的部分元素。插图:

当形状超出 canvas 边界时,您需要绘制两次。先画主要部分,然后画出相同的部分宽度偏移,这样就给人一种在另一边显示的错觉。

手动绘制两次

这里绘制了一个从右到左的形状,当形状在左边缘之外时,它将在右边缘重新绘制,代表左侧不可见的部分。对于相反的方式(从左到右)原理是一样的,只是使用宽度为 canvas' 的 x 而不是 0.

var ctx = document.querySelector("canvas").getContext("2d"),
    x = 100,                                         // start position
    w = 200;                                         // shape width

ctx.fillStyle = "#777";

(function loop() {
  ctx.clearRect(0, 0, 300, 150);                     // clear canvas
  ctx.fillRect(x, 0, w, 150);                        // draw main part/image/shape
  if (x < 0) {                                       // should rotate? draw secondary
    ctx.fillRect(ctx.canvas.width + x, 0, w, 150);   // use canvas width + x (x<0)
  }

  x -= 7;                                            // animate
  if (x <= -w) x = ctx.canvas.width + x;             // at some point reset x

  requestAnimationFrame(loop)
})();
<canvas></canvas>

翻译后的模式

为了简化这一点,可以使用 CanvasPattern。 canvas 的更高版本允许对模式本身进行局部变换,但由于目前这还没有广泛传播,我将展示一个使用普通变换和补偿 x 位置的示例:

var ctx = document.querySelector("canvas").getContext("2d"),
    pattern,
    x = 100,                                         // start position
    w = 200;                                         // shape width

// create pattern
ctx.fillStyle = "#777";
ctx.fillRect(x, 0, w, 150);                          // draw main part/image/shape
pattern = ctx.createPattern(ctx.canvas, "repeat");   // use current canvas as pattern
ctx.fillStyle = pattern;                             // set pattern as fillStyle

(function loop() {
  ctx.setTransform(1,0,0,1,0,0);                     // reset transforms
  ctx.clearRect(0, 0, 300, 150);                     // clear canvas
  ctx.setTransform(1,0,0,1,x,0);                     // translate absolute x
  ctx.fillRect(-x, 0, 300, 150);                     // fill using pattern, compensate transform
  x -= 7;                                            // animate

  requestAnimationFrame(loop)
})();
<canvas></canvas>