> I wanted to come up with a flashlight that really works for all elements on the page, but I don't think any combination of DOM elements and mix-blend-modes would do it.
This doesn’t seem to work below one screenful of content, though, and I’m not sure why and don’t intend to spend the time required to make it work. The SVG size technique I’ve used is a bit dodgy (in a fun kind of way) anyway. You’d probably be better to have a separate `position: fixed` element that sits on top of everything, and apply the mask to it.
I actually had the same thought and came up with a much simpler solution for this years ago, a giant box-shadow + border radius: https://codepen.io/wbobeirne/pen/WvyBQM.
The mix-blend-mode trick is cool for all of the variety of effects though!
The first time I came across the spotlight effect was in a Facebook game - I can't remember the game's name, but it was very much like Mystery Manor[1].
Kudos to the OP for coding up the feature in CSS. The effect is fairly easy to recreate in the canvas element, using a radialGradient in a rectangle for a simple spotlight or, for the replacement effect, playing with globalcompositeoperation when rendering the scene.
Here's my spotlight demo, which I did for a CodePen Challenge last year (warning: page will ask to use your device's camera): https://codepen.io/kaliedarik/pen/gORXpya
A bit of a tangent, but gosh did I find Dancer in the Dark to be traumatizing. So sad! Bjork (whom I love) said she wouldn't do movies again after that one but I was happy to see her pop up in The Northman trailer.
I wonder if you could put the canvas/flashlight controls in a fixed corner of the page (instead of inline as you scroll up & down). Fixed, omnipresent controls would be more video game like.
Yes, good idea. For the purpose of this article I want the reader to encounter the features as I talk about them, but for other applications I would fix the controls.
Plus, inlined controls add to the suspense -- you might truly get lost in the dark! And breathe a sigh of relief when you find the button again :)
It would be faster to place the gradient on an overlay and move it using CSS transform. The method above causes a recalculation of the entire gradient on every move; transform would just move the already rendered texture (in hardware on modern browsers).
This works too. I'm finding that while the dev tools are open, the transform method drops to very low fps whereas the recalculating method only loses a bit of fps. While the dev tools are closed they seem to be equal on my computer. Of course on a weaker computer there might be a bigger difference.
dsmmcken has shown that making a full blackout with CSS is possible with clip-path, but at the time I wrote this, I didn't know that.
The CSS comes in the form of the mix-blend-mode divs, "grayscale", "bright white", "inverse", etc. They are more like lenses than flashlights since they don't illuminate what's not already there, but flashlights were my inspiration for doing this so that's the term I stuck with, though I did use the word lens once.
The CSS idea came first, and the canvas idea came second when I wanted to make a full blackout and didn't know about clip-path.
I think CSS clip-path might be a solution like you want but without the canvas. Just tried it out here to confirm: https://codepen.io/dsmmcken/pen/BaJqrwX