我正在使用 HTML5 Canvas 元素创建游戏,作为视觉效果之一,我想创建发光(如灯光)效果。以前对于发光效果,我找到了涉及创建形状阴影的解决方案,但这些需要实体形状或对象来投射阴影。我正在寻找的是一种创建类似环境光发光的方法,具有源位置但该位置没有对象。
我想到的是定义一个中心点x并y创建数百个同心圆,每个比上一个大 1px 并且每个都具有非常低的不透明度,以便它们一起创建一个实心中心和一个透明边缘。然而,这在计算上非常繁重,而且看起来一点也不优雅,因为产生的光晕看起来很尴尬。
虽然这就是我所要求的全部内容,我很乐意就此打住,但如果您的解决方案是 A) 计算上的轻量级,B) 可修改以创建聚焦的光方向,或者甚至更好,C) 如果有,则加分是一种创建“倒置”照明系统的方法,在该系统中,整个屏幕被蒙版变暗,并在有光的地方提升阴影。
我进行了几次搜索,但没有一个发现任何特别有启发性的结果。
所以我不太确定你想要什么,但我希望下面的代码片段会有所帮助。
与其创建许多同心圆,不如创建一个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>| 归档时间: | 
 | 
| 查看次数: | 1064 次 | 
| 最近记录: |