gpt4 book ai didi

javascript - HTML5 Canvas : Applying a gradient to shadow

转载 作者:行者123 更新时间:2023-12-02 15:22:33 25 4
gpt4 key购买 nike

我很惊讶地发现canvas API显然不允许你像这样对阴影应用渐变:

var grad = ctx.createLinearGradient(fromX, fromY, toX, toY);

grad.addColorStop(0, "red");
grad.addColorStop(1, "blue");

ctx.strokeStyle = grad;
ctx.lineWidth = 3;
ctx.shadowBlur = 10;
ctx.shadowColor = grad; // doesn't seem to work

ctx.beginPath();
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.closePath();
ctx.stroke();

// linear gradient from start to end of line
var canvas = document.getElementById('mycanvas'),
ctx = canvas.getContext('2d'),
fromX = 3,
fromY = 3,
toX = 197,
toY = 197,
grad = ctx.createLinearGradient(fromX, fromY, toX, toY);

canvas.width = 200;
canvas.height = 200;

grad.addColorStop(0, "red");
grad.addColorStop(1, "blue");

ctx.strokeStyle = grad;
ctx.lineWidth = 3;
ctx.shadowBlur = 20;
ctx.shadowColor = grad;

ctx.beginPath();
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.closePath();
ctx.stroke();
body {
background: black
}
<canvas id="mycanvas"></canvas>

一种解决方法是简单地绘制线条/形状/等。以不同的尺寸和不透明度多次以获得相似的结果:

var grad = ctx.createLinearGradient(fromX, fromY, toX, toY);

canvas.width = 200;
canvas.height = 200;

grad.addColorStop(0, "red");
grad.addColorStop(1, "blue");

ctx.strokeStyle = grad;
ctx.lineWidth = 3;
//ctx.shadowBlur = 20;
//ctx.shadowColor = grad;

for (var i = 10; i > 1; i--) {
ctx.lineWidth = i;
ctx.globalAlpha = 1 / i;
ctx.beginPath();
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.closePath();
ctx.stroke();
}

// linear gradient from start to end of line
var canvas = document.getElementById('mycanvas'),
ctx = canvas.getContext('2d'),
fromX = 3,
fromY = 3,
toX = 197,
toY = 197,
grad = ctx.createLinearGradient(fromX, fromY, toX, toY);

canvas.width = 200;
canvas.height = 200;

grad.addColorStop(0, "red");
grad.addColorStop(1, "blue");

ctx.strokeStyle = grad;
ctx.lineWidth = 3;
//ctx.shadowBlur = 20;
//ctx.shadowColor = grad;

for (var i = 10; i > 1; i--) {
ctx.lineWidth = i;
ctx.globalAlpha = 1 / i;
ctx.beginPath();
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.closePath();
ctx.stroke();
}
body {
background: black;
}
<canvas id="mycanvas"></canvas>

这是比较。虽然变化很细微,但右图大致显示了预期的效果。

line1 line2

有更好的方法吗?我想有一种比多次绘制同一事物更有效的方法。有谁知道提供这种功能的库吗?

最佳答案

使用 Canvas 2d 上下文的 filter 属性。 MDN filter尽管(像往常一样)它确实说 Chrome 不支持过滤器,但从 Beta 版本开始就已经支持过滤器了。对于 IE 我不知道,对于 FF 它已经支持了一段时间了。如果您使用它,则必须对其进行测试。

更新

支持并不是自动的。虽然 MDN 显示对 Firefox 的支持,但您必须将 canvas.filters.enable 设置为 true (无论这意味着什么,我相信 Firefox 爱好者都知道),而对于 chrome,您必须使用接缝到 chrome://flags 然后将实验 Canvas 功能设置为启用

更多由于支持如此有限,我添加了一个后备方案。它使用第二个 Canvas 通过使用 ctx.imageSmoothingEnabled=true; 来模糊阴影,并以模糊量一半的比例进行渲染。因此,如果模糊是 5 像素,那么背景 Canvas 的大小必须是十分之一。然后在原始 Canvas 上以全尺寸渲染背景 Canvas 并启用平滑处理。

不是最好的结果,也不利于线条,但它速度快,可以用来优化结果。

展示如何检测支持和使用的片段。

var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");



var g = ctx.createLinearGradient(10,10,100,100);
for(var i = 0; i <= 1; i+= 0.05){
g.addColorStop(i,"hsl("+Math.floor(i*360)+",100%,50%)");
}
var gDark = ctx.createLinearGradient(20,20,100,100);
for(var i = 0; i <= 1; i+= 0.05){
gDark.addColorStop(i,"hsl("+Math.floor(i*360)+",100%,30%)");
}
ctx.font = "16px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "hanging";
if(ctx.filter !== undefined){
ctx.fillText("Using filter.",65,125);
ctx.fillStyle = gDark;
ctx.filter = "blur(5px)"; // set the blur
ctx.fillRect(20,20,100,100); // draw the shadow
ctx.fillStyle = g; // set the lighter gradoent
ctx.filter = "blur(0px)"; // remove the blur
ctx.lineWidth = 2;
ctx.strokeStyle = "black"
ctx.fillRect(10,10,100,100); // draw the box
ctx.strokeRect(10,10,100,100); // with line to look nice.

}else{
// fallback method
ctx.fillText("Using Fallback.",60,125);
var can = document.createElement("canvas"); // create a second canvas
can.width = Math.floor(canvas.width/10); // size to make one pixel the
can.height =Math.floor(canvas.height/10); // size of the blur
var ctxS = can.getContext("2d");
ctxS.setTransform(1/10,0,0,1/10,0,0); // set scale so can work in same coords
ctxS.fillStyle = gDark;
ctxS.fillRect(20,20,100,100); // draw the shadow
ctx.imageSmoothingEnabled=true;
ctx.drawImage(can,0,0,canvas.width,canvas.height);
}
ctx.fillStyle = g; // set the lighter gradoent
ctx.lineWidth = 2;
ctx.strokeStyle = "black"
ctx.fillRect(10,10,100,100); // draw the box
ctx.strokeRect(10,10,100,100); // with line to look nice.
#canV {
width:200px;
height:200px;
}
<canvas id="canV" width = 200 height =200></canvas>

关于javascript - HTML5 Canvas : Applying a gradient to shadow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33924884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com