Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
155 views
in Technique[技术] by (71.8m points)

javascript - Using canvas, how to cut holes with inset shadows into an image?

Using canvas, I'm trying to cut a series of round holes into an image. Additionally, each hole should have an inset drop shadow that would make it look as if the image is slightly hovering over the background.

Here is what I've managed to do:

  1. Cut holes into an image using globalCompositeOperation = "destination-top"
  2. Cut out one hole from a background shape using "opposite winding" (drawing counter-clockwise, then clockwise)

The second attempt, however, does not seem to be viable for multiple holes on an image for these two reasons:

  • AFAIK, can't draw an image counter-clockwise
  • AFAIK, for opposite drawing technique to work, I can't close the path in between calls to arc

Here is what I currently have:

let cvs = document.querySelector("canvas");
let ctx = cvs.getContext("2d");
let img = new Image();
img.addEventListener("load", function() {
  ctx.drawImage(img, 0, 0, 256, 256);
  ctx.globalCompositeOperation = "destination-out";
  hole(ctx, 64, 64, 32);
  hole(ctx, 192, 64, 32);
  hole(ctx, 64, 192, 32);
  hole(ctx, 192, 192, 32);
});
img.src = "https://placeimg.com/256/256/nature";

function hole(ctx, x, y, r, ccw=false) {
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI * 2, ccw);
    ctx.closePath();
    ctx.fill();
}
<canvas width="256" height="256"></canvas>
question from:https://stackoverflow.com/questions/65885761/using-canvas-how-to-cut-holes-with-inset-shadows-into-an-image

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I suggest you use a second canvas to help create the effect you're after, alongside shadowOffset and shadowColor.

let cvs = document.querySelector("canvas");
let ctx = cvs.getContext("2d");
let img = new Image();

img.addEventListener("load", function() {
  let cvs2 = document.createElement('canvas');
  cvs2.width = 256;
  cvs2.height = 256;
  ctx2 = cvs2.getContext("2d");

  hole(ctx2, 64, 64, 32);
  hole(ctx2, 192, 64, 32);
  hole(ctx2, 64, 192, 32);
  hole(ctx2, 192, 192, 32);

  ctx2.globalCompositeOperation = "source-out";
  ctx2.drawImage(img, 0, 0, 256, 256);

  ctx.shadowOffsetX = 4;
  ctx.shadowOffsetY = 4;
  ctx.shadowBlur = 8;
  ctx.shadowColor = 'black';
  ctx.drawImage(cvs2, 0, 0, 256, 256);
});
img.src = "https://placeimg.com/256/256/nature";

function hole(ctx, x, y, r, ccw = false) {
  ctx.beginPath();
  ctx.arc(x, y, r, 0, Math.PI * 2, ccw);
  ctx.closePath();
  ctx.fill();
}
<canvas width="256" height="256"></canvas>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...