【问题标题】:Efficient HTML5 Canvas Glow Effect without shape没有形状的高效 HTML5 Canvas Glow 效果
【发布时间】:2017-04-15 17:51:07
【问题描述】:

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

我的想法是定义一个中心点 xy 并创建数百个同心圆,每个都比上一个大 1px 并且每个不透明度都非常低,这样它们就可以共同创建一个实心圆一个透明的边缘。然而,这计算量很大,而且看起来一点也不优雅,因为产生的光晕看起来很尴尬。

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

我已经进行了几次搜索,但都没有找到任何特别有启发性的结果。

【问题讨论】:

  • 您至少可以包含一些您所想的模型。就目前而言,似乎相当广泛。但是要探索的东西:径向渐变与滤镜模糊 + gCO 混合模式相结合?

标签: javascript html canvas


【解决方案1】:

所以我不太确定你想要什么,但我希望下面的 sn-p 会有所帮助。

创建一个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>

【讨论】:

  • 一切都好,但模糊滤镜会降低帧率,为什么不在创建 grad 画布时这样做。
  • @Blindman67 脑放屁?你完全正确,这个过滤器应该只应用于渐变画布......当回到键盘时会修复。
  • 用我的手机做的,但无法测试它是否破坏了任何东西(没有鼠标移动...)
  • 非常好的演示,这正是我想要的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 2012-01-29
相关资源
最近更新 更多