我创建了一个程序来生成行星精灵。我这样做是通过创建一个圆形路径,运行ctx.clip()将以下所有图层保留在圆圈内,然后绘制一个黑色和透明的纹理图层,然后在整个画布上绘制一个随机着色的矩形,再绘制一个阴影和辉光最重要的是问题是剪切后圆下还会出现一条彩色的线,我不确定为什么。我需要将其删除。

这是一个小提琴。最后一行将代码设置为每半秒循环一次:https://jsfiddle.net/tzkwmzqu/4/

最佳答案

我不确定我是否理解您的问题,但是我将假定您在谈论anti-aliasing问题。

目前,您在裁剪区域上绘制了很多东西。
在每次绘制时,都会使用新的抗锯齿工件来平滑最新的绘制。最后,原本应该是半透明的像素现在变成了完全不透明的像素。
另一方面,像globalCompositeOperation这样的'destination-in',只需要一个图形即可进行合成(〜剪切)。因此,您不会积累工件。但是,即使您这样做了,gCO也是全球性的,并且由于考虑了透明度,因此积累的重要性将降低。



var ctx1 = clip.getContext('2d');
var ctx2 = gCO.getContext('2d');
var ctx3 = gCO2.getContext('2d');

ctx1.beginPath();
ctx1.arc(150, 150, 150, 0, Math.PI*2)
ctx1.clip();
// drawing multiple times on this clipped area will increase artifacts
ctx1.fillRect(0,0,300, 150);
ctx1.fillRect(0,0,300, 150);
ctx1.fillRect(0,0,300, 150);
ctx1.fillRect(0,0,300, 150);

ctx2.beginPath();
ctx2.arc(150, 150, 150, 0, Math.PI*2)
ctx2.fillRect(0,0,300, 150);
ctx2.globalCompositeOperation = 'destination-in';
//With gCO you only draw once, but even if you did draw multiple times, there would still be less artifacts
ctx2.fill();
ctx2.fill();
ctx2.fill();
ctx2.fill();
ctx2.globalCompositeOperation = 'source-over';

ctx3.beginPath();
ctx3.arc(150, 150, 150, 0, Math.PI*2)
ctx3.fillRect(0,0,300, 150);
ctx3.globalCompositeOperation = 'destination-in';
// only one drawing needed:
ctx3.fill();
ctx3.globalCompositeOperation = 'source-over';

ctx1.fillStyle = ctx2.fillStyle = ctx3.fillStyle = "white";
ctx1.fillText('clipping', 120, 100);
ctx2.fillText('compositing', 120, 100);
ctx3.fillText('single compositing', 120, 100);

canvas{
  border: 1px solid;
  }

<canvas id="clip"></canvas><canvas id="gCO"></canvas><canvas id="gCO2"></canvas>





有关您的代码的一些无关说明:

closePath不会标记路径声明的结尾,只有新的beginPath()调用会标记。 ctx.fillStyle = 'transparent'; ctx.fill()不会做任何事情。只有putImageDataclearRect方法和globalCompositeOperation +绘制方法可以产生透明像素。

以上是所有这些内容的一个摘要:



/* Load images */
var texture = new Image();
texture.src = "http://i.imgur.com/0qMwa8p.png";
var shadow = new Image();
shadow.src = "http://i.imgur.com/pX3HVFY.png";

/* Create the canvas and context references */
var canvas = document.getElementById("game");
canvas.style.width = (canvas.width = 512) + "px";
canvas.style.height = (canvas.height = 512) + "px";
var ctx = canvas.getContext("2d");

/* render */
function render() {
  /* Size of planets */
  var scale = Math.random() + 1


  // We don't need to save/restore the canvas state now,
  // simply remember to set the gCO back to 'source-over'
  // here it done at the end of the function

  /* Clear canvas for redraw */
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  /* Place texture onto planet */
  ctx.globalAlpha = Math.random() * .5 + .5;
  ctx.drawImage(texture, (Math.round(Math.random() * 256) - 128 * scale), (Math.round(Math.random() * 256) - 128 * scale), texture.naturalWidth * scale, texture.naturalHeight * scale)

  /* Color Planet */
  ctx.globalAlpha = 1;
  ctx.globalCompositeOperation = "multiply";
  var color = "hsl(" + Math.random() * 256 + ", 100%, 50%)"
  ctx.fillStyle = color;
  ctx.fillRect(0, 0, canvas.width, canvas.height)

  /* Give planet its shine and shadow */
  ctx.globalCompositeOperation = "source-over";
  ctx.drawImage(shadow, Math.round(Math.random() * 200 - 128 * scale), Math.round(Math.random() * 200 - 128 * scale), shadow.naturalWidth * scale, shadow.naturalHeight * scale)

  // instead of clipping, use gCO
  ctx.globalCompositeOperation = 'destination-in';
  ctx.beginPath();
  ctx.arc(256, 256, 128 * scale, 0, 2 * Math.PI);
  ctx.fill();
  // reset gCO
  ctx.globalCompositeOperation = 'source-over';
}
render()
window.interval = setInterval(render, 500)

#game {
  border: 1px solid black;
  background-color: black;
}

<canvas id="game"></canvas>

关于javascript - 在圆上使用的HTML5 Canvas ctx.clip()方法在圆下方留下一条线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40499791/

10-12 00:13