内阴影
Canvas 没有 CSS 的 inner-shadow
。
- 画布将遮蔽填充形状的外部。
- 画布会在描边形状的内部和外部遮挡阴影。
但是使用合成创建内阴影很容易。
带有内阴影的笔划
要使用内部阴影创建笔划,请使用 destination-in
合成,这会导致现有内容仅保留现有内容与新内容重叠的位置。删除不与新内容重叠的现有内容。
- **描绘带阴影的形状。**阴影将从笔划向外和向内延伸。我们必须摆脱外阴影 - 留下所需的内阴影。
- 将合成设置为
destination-in
,它将现有的描边阴影保留在任何新图形重叠的位置。 - **填充形状。**这会导致在擦除外部阴影时保留笔划和内部阴影。好吧,不完全是! 由于笔划在填充形状的一半内侧和一半外侧,因此笔划的外侧一半也将被擦除。修复是将
context.lineWidth
加倍,因此双倍尺寸笔划的一半仍在填充形状内。
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);
// draw an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);
// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;
// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();
// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();
// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';
function defineRoundedRect(x,y,width,height,radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
带内阴影的描边填充
要使用内部阴影创建填充,请按照上面的步骤#1-3 进行操作,但进一步使用 destination-over
合成,这会导致在现有内容下绘制新内容。
- 将合成设置为
destination-over
,这会导致在现有内阴影下绘制填充。 - **** 通过将
context.shadowColor
设置为透明色来关闭阴影。 - **** 用所需的颜色填充形状。形状将填充在现有内阴影下方。
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);
// draw an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);
// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;
// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();
// stop shadowing
ctx.shadowColor='rgba(0,0,0,0)';
// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();
// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='gold';
ctx.fill();
// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';
function defineRoundedRect(x,y,width,height,radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
非描边填充内阴影
要绘制带有内部阴影但没有笔划的填充形状,可以在画布外绘制笔划并使用 shadowOffsetX
将阴影推回到画布上。
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);
// define an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30-500,30,100,75,10);
// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;
ctx.shadowOffsetX=500;
// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();
// stop shadowing
ctx.shadowColor='rgba(0,0,0,0)';
// redefine an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);
// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();
// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='gold';
ctx.fill();
// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';
function defineRoundedRect(x,y,width,height,radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}