2017-04-15 147 views
0

我使用HTML5 Canvas元素创建了一个游戏,并将其作为我希望创建辉光(如光线)效果的视觉效果之一。以前为了发光效果,我找到了创建形状阴影的解决方案,但这些都需要一个坚实的形状或物体来投射阴影。我正在寻找的是一种创建类似环境光源的位置,但没有物体位置的方法。高效的HTML5 Canvas无形状的辉光效果

东西我想到的是定义一个中心点xy和创建数百个同心圆,每1px的比上,并且每个具有非常低透明度大,所以他们一起创造了坚实的中心和透明边界。但是,这个计算量非常大,看起来并不高雅,因为所产生的辉光看起来很尴尬。虽然这就是我所要求的全部内容,但如果你的解决方案是A)计算光,B)可以修改以创建聚焦的光线方向,甚至更好, C)是否有创建一个“倒置”灯光系统的方法,其中整个屏幕被面罩变暗,而灯罩在有光的地方被抬起。

我已经做了几次搜索,但没有人发现任何特别照明的结果。

+0

你能不能至少包括你心中已经有了一些什么原型。看起来相当宽泛。但要探索的事情:径向渐变与滤镜模糊+ gCO混合模式相结合? – Kaiido

回答

2

所以我不太清楚你想要什么,但我希望下面的代码片段可以帮助。

而不是创建很多同心圆,创建一个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>

+0

所有不错的,但模糊过滤器将杀死帧速率,为什么不当你创建毕业画布。 – Blindman67

+0

@ Blindman67脑屁?你是完全正确的,这个过滤器只能应用在渐变画布上......会在返回到键盘时修复。 – Kaiido

+0

做到了从我的手机,但无法测试是否它破坏了任何东西(没有鼠标移动...) – Kaiido