简体   繁体   中英

Efficient HTML5 Canvas Glow Effect without shape

I am creating a game using the HTML5 Canvas element, and as one of the visual effects I would like to create a glow (like a light) effect. Previously for glow effects I found solutions involving creating shadows of shapes, but these require a solid shape or object to cast the shadow. What I am looking for is a way to create something like an ambient light glow with a source location but no object at the position.

Something I have thought of was to define a centerpoint x and y and create hundreds of concentric circles, each 1px larger than the last and each with a very low opacity, so that together they create a solid center and a transparent edge. However, this is very computationally heavy and does not seem elegant at all, as the resulting glow looks awkward.

While this is all that I am asking of and I would be more than happy to stop here, bonus points if your solution is A) computationally light, B) modifiable to create a focused direction of light, or even better, C) if there was a way to create an "inverted" light system in which the entire screen is darkened by a mask and the shade is lifted where there is light.

I have done several searches, but none have turned up any particularly illuminating results.

So I'm not quite sure what you want, but I hope the following snippet will help.

Instead of creating a lot of concentric circles, create one radialGradient.
Then you can combine this radial gradient with some blending, and even filters to modify the effect as you wish.

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM