HTML5 画布图像上的插入阴影

Try*_*nJS 1 html javascript css canvas

我以前见过这个问题,但给出的答案是针对通过路径绘制的画布图像,但是,我正在绘制图像。

是否可以创建一个inset-shadow

context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 10;
context.shadowColor = 'rgba(30,30,30, 0.4)';

var imgOne = new Image();
imgOne.onload = function() {
    context.drawImage(imgOne, 0, 0);
};
imgOne.src = "./public/circle.png";
Run Code Online (Sandbox Code Playgroud)

所以我在上面画了圆圈图。我现在在圆圈外面有一个轻微的阴影,我怎么能得到这个inset而不是offset

mar*_*rkE 6

Canvas 会在图像从不透明变为透明的地方产生阴影,因此,正如 K3N 在其正确答案中所示,您可以将图像翻过来(不透明变为透明,反之亦然),以便将阴影绘制在圆圈内。

如果您知道圆的中心点和半径,则可以使用描边路径来创建插入圆阴影。这是一个例子:

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

context.beginPath();
context.arc(cw/2,ch/2,75,0,Math.PI*2);
context.fillStyle='lightcyan';
context.fill();

context.globalCompositeOperation='source-atop';

context.shadowOffsetX = 500;
context.shadowOffsetY = 0;
context.shadowBlur = 15;
context.shadowColor = 'rgba(30,30,30,1)';

context.beginPath();
context.arc(cw/2-500,ch/2,75,0,Math.PI*2);
context.stroke();
context.stroke();
context.stroke();

context.globalCompositeOperation='source-over';
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" width=300 height=300></canvas>
Run Code Online (Sandbox Code Playgroud)

如果您的路径不规则或难以用数学方法定义,您还可以使用边缘路径检测算法。一种常见的边缘路径算法是Marching Squares。Stackoverflow 的 K3N 编写了一个很好的Marching Squares 算法


小智 5

组合链

使用一系列合成+绘制操作来获得插入阴影。

注意:该解决方案在创建时需要对画布元素的独占访问权限,因此要么在屏幕外画布上执行此操作并绘制回主画布,要么如果可能,在生成此画布后计划要绘制的辅助图形。

需要的步骤:

  • 在原始图像中绘制
  • 使用xor合成反转填充画布的 alpha 通道
  • 定义阴影并将其自身拉回
  • 取消阴影并在原始图像中绘制 ( destination-atop)

结果

var ctx = c.getContext("2d"), img = new Image;
img.onload = function() {

  // draw in image to main canvas
  ctx.drawImage(this, 0, 0);

  // invert alpha channel
  ctx.globalCompositeOperation = "xor";
  ctx.fillRect(0, 0, c.width, c.height);

  // draw itself again using drop-shadow filter
  ctx.shadowBlur = 7*2;  // use double of what is in CSS filter (Chrome x4)
  ctx.shadowOffsetX = ctx.shadowOffsetY = 5;
  ctx.shadowColor = "#000";
  ctx.drawImage(c, 0, 0);

  // draw original image with background mixed on top
  ctx.globalCompositeOperation = "destination-atop";
  ctx.shadowColor = "transparent";                  // remove shadow !
  ctx.drawImage(this, 0, 0);
}
img.src = "http://i.imgur.com/Qrfga2b.png";
Run Code Online (Sandbox Code Playgroud)
<canvas id=c height=300></canvas>
Run Code Online (Sandbox Code Playgroud)