高效的HTML5 Canvas Glow Effect没有形状

时间:2017-04-15 04:24:30

标签: javascript html5 canvas

我正在使用HTML5 Canvas元素创建游戏,并且作为视觉效果之一,我想创建一个发光(如光)效果。以前对于发光效果我发现了涉及创建形状阴影的解决方案,但这些需要一个实体形状或对象来投射阴影。我正在寻找的是一种方法来创建类似环境光发光的东西,其中包含源位置但位置没有物体。

我想到的是定义一个中心点xy并创建数百个同心圆,每个圆圈比最后一个大1px且每个都具有非常低的不透明度,因此它们一起创建坚实的中心和透明的边缘。然而,这在计算上非常重,并且看起来并不优雅,因为产生的光晕看起来很尴尬。

虽然这就是我所要求的,但我很乐意在这里停下来,如果你的解决方案是A)计算上很轻,B)可以修改,以创建一个聚焦的光方向,甚至更好,C )如果有办法建立一个“倒置”的灯光系统,其中整个屏幕被一个面罩变暗,并且在有光的地方抬起灯罩。

我已经完成了几次搜索,但没有一次搜索出现任何特别有启发性的结果。

1 个答案:

答案 0 :(得分:3)

所以我不太确定你想要什么,但我希望以下代码片段会有所帮助。

创建一个radialGradient,而不是创建很多同心圆 然后,您可以将此径向渐变与某些混合相结合,甚至可以根据需要使用滤镜来修改效果。



var img = new Image();
img.onload = init;
img.src = "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/car.svg";
var ctx = c.getContext('2d');
var gradCtx = c.cloneNode().getContext('2d');
var w, h;
var ratio;

function init() {
  w = c.width = gradCtx.canvas.width = img.width;
  h = c.height = gradCtx.canvas.height = img.height;
  draw(w / 2, h / 2)
  updateGradient();
  c.onmousemove = throttle(handleMouseMove);
}

function updateGradient() {
  var grad = gradCtx.createRadialGradient(w / 2, h / 2, w / 8, w / 2, h / 2, 0);
  grad.addColorStop(0, 'transparent');
  grad.addColorStop(1, 'white');
  gradCtx.fillStyle = grad;
  gradCtx.filter = "blur(5px)";
  gradCtx.fillRect(0, 0, w, h);
}

function handleMouseMove(evt) {
  var rect = c.getBoundingClientRect();
  var x = evt.clientX - rect.left;
  var y = evt.clientY - rect.top;
  draw(x, y);
}

function draw(x, y) {
  ctx.clearRect(0, 0, w, h);
  ctx.globalCompositeOperation = 'source-over';
  ctx.drawImage(img, 0, 0);
  ctx.globalCompositeOperation = 'destination-in';
  ctx.drawImage(gradCtx.canvas, x - w / 2, y - h / 2);
  ctx.globalCompositeOperation = 'lighten';
  ctx.fillRect(0, 0, w, h);
}

function throttle(callback) {
  var active = false; // a simple flag
  var evt; // to keep track of the last event
  var handler = function() { // fired only when screen has refreshed
    active = false; // release our flag 
    callback(evt);
  }
  return function handleEvent(e) { // the actual event handler
    evt = e; // save our event at each call
    if (!active) { // only if we weren't already doing it
      active = true; // raise the flag
      requestAnimationFrame(handler); // wait for next screen refresh
    };
  }
}

<canvas id="c"></canvas>
&#13;
&#13;
&#13;