HTML5 Canvas:对阴影应用渐变 [英] HTML5 Canvas: Applying a gradient to shadow

查看:72
本文介绍了HTML5 Canvas:对阴影应用渐变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was surprised to find out that apparently the canvas API does not allow you to apply gradients to shadows like this:

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>

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

One workaround is to simply draw the line/shape/etc. multiple times at different sizes and opacity to get a similar result:

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>

这是比较。尽管更改很小,但正确的图像大致显示了所需的效果。

Here's the comparison. Although the change is subtle, the right image shows roughly the desired effect.


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

Is there a better way of doing this? I imagine there's a more efficient way than drawing the same thing multiple times. Does anyone know of a library that provides this kind of functionality?

推荐答案

使用过滤器属性。 MDN过滤器尽管(确实)它确实说过滤器Chrome不支持该功能,但从Beta版本开始已有一段时间了。对于IE,我不知道;对于FF,它已经受支持了一段时间。

Use the filter property of the canvas 2d context. MDN filter though (as usual) it does say filter is not supported on Chrome it has been from some time on the Beta version. For IE I do not know and for FF it has been supported for some time. You will have to test for it if you use it.

更新

支持不会自动缝合。尽管MDN显示了对Firefox的支持,但您必须将 canvas.filters.enable 设置为 true (无论如何,确保Firefox爱好者知道)和chrome接缝,则必须转到 chrome:// flags ,然后将实验画布功能设置为已启用

Support does not seam to be automatic. Though MDN shows support for Firefox you must set the canvas.filters.enable to true (whatever that means, I am sure firefox lovers know) and seams for chrome you must go to chrome://flags then set experimental canvas features to enabled

更多
我添加了一个后备功能,因为这样有限的支持。它使用第二个画布通过使用 ctx.imageSmoothingEnabled = true; 并以一半模糊量进行渲染来模糊阴影。因此,如果模糊为5像素,则背景画布中的大小必须为十分之一。然后在原始画布上渲染完整的背景画布并进行平滑处理。

More I have added a fallback as there is such limited support. It uses a second canvas to blur the shadow by using the ctx.imageSmoothingEnabled=true; and rendering at a scale one half the blur amount. So if blur is 5 pixels then in background canvas must be one tenth the size. Then on the original canvas render the background canvas at full size with smoothing on.

没有最好的结果,也不会对线条产生好处,但是它的速度很快并且可以播放

No the best result and will no be good for lines, but its fast and can be played around with to optimise results.

该片段显示如何检测支持和使用。

Snippet to show how to detect support and use.

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>

这篇关于HTML5 Canvas:对阴影应用渐变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆