Reputation: 529
Basically, I want to make an empty div that I can put anywhere on the page, and it will invert the colors of everything behind it. Is this possible? (It shouldn't invert entire elements that are overlapped, only the part covered by the div)
Upvotes: 2
Views: 2907
Reputation: 10821
You can implement it (or any other filter) using the backdrop-filter
css property.
.overlay {
/* The invert effect */
-webkit-backdrop-filter: invert(100%);
backdrop-filter: invert(100%);
position: fixed;
top: 50px;
left: 50px;
width: 100px;
height: 50px;
border: solid 1px blue;
transition: all 0.3s ease;
}
.overlay:hover {
left: 100px;
}
<div class="overlay"></div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam dignissim elementum mattis. Pellentesque lacus velit, sollicitudin eget tincidunt et, dapibus a tortor. Vestibulum ultrices nisi ut turpis ultricies interdum. Proin pellentesque purus rutrum, pretium justo ac, scelerisque sem. Suspendisse potenti. Sed iaculis eu velit sed maximus. Phasellus vestibulum in tellus sit amet euismod. Donec id faucibus lectus. Aenean eu pretium risus, ut pharetra odio. Ut hendrerit molestie hendrerit. Morbi consectetur ultricies elit ut convallis. Quisque cursus odio id lacinia ultrices. Nulla eu ligula et mauris laoreet cursus sed nec orci. Donec eu vulputate leo, id scelerisque quam. Aenean dignissim placerat pharetra.</p>
<p>Vestibulum ac fringilla ipsum. Vivamus venenatis non sem sed hendrerit. Etiam mollis libero lorem. Nullam pharetra nulla vitae libero porttitor sollicitudin. Maecenas non sapien a tellus rutrum pellentesque ac non nisi. Aenean rhoncus et arcu ac suscipit. Mauris in nunc quis dolor aliquet pharetra. Nulla mi arcu, mollis ac ligula vel, vestibulum pretium massa. Quisque malesuada justo eu imperdiet lobortis. Mauris elit arcu, feugiat id vulputate quis, efficitur ut neque. In dignissim dignissim euismod. Suspendisse ac arcu ipsum. Cras dignissim justo risus, et blandit ligula egestas eu. Nunc massa purus, hendrerit quis lacinia non, luctus at erat.</p>
Unfortunately this CSS property is not widely supported by browsers.
Upvotes: 4
Reputation: 8036
The easiest way is to use CSS3 property mix-blend-mode
. It's just one line of code!
.invert-everything-behind {
mix-blend-mode: exclusion;
}
See: https://css-tricks.com/almanac/properties/m/mix-blend-mode/
Upvotes: 2
Reputation: 165
Or in straight SVG, you can invert the spectrum of a filtered area just using feComponentTransfer as in http://cs.sru.edu/~svg/Chapter05/G05xx16.svg
Upvotes: 1
Reputation: 2339
Maybe this is what you need: example
function start() {
var canvas1 = document.getElementById("canvas");
var ctx1 = canvas1.getContext("2d");
var canvas2 = document.getElementById("over");
var ctx2 = canvas2.getContext("2d");
// Just put a colorfull random background to play with.
randomFill( ctx1 );
// Animation of the lens.
var x = Math.random() * 100;
var y = Math.random() * 100;
var speed = .02;
var vx = .03 + Math.random() * speed;
var vy = .03 + Math.random() * speed;
var lastTime = 0;
function anim( time ) {
window.requestAnimationFrame( anim );
if (lastTime == 0) {
lastTime = time;
} else {
var delay = time - lastTime;
lastTime = time;
x += delay * vx;
y += delay * vy;
if (x < 0) {
x = 0;
vx = -vx;
}
else if (x > 299) {
x = 299;
vx = -vx;
}
if (y < 0) {
y = 0;
vy = -vy;
}
else if (y > 299) {
y = 299;
vy = -vy;
}
canvas2.style.top = Math.floor(y) + "px";
canvas2.style.left = Math.floor(x) + "px";
}
applyFilter( ctx1, ctx2, x, y );
}
window.requestAnimationFrame( anim );
}
function randomFill( ctx ) {
var i, x, y, w, h;
for (i = 0 ; i < 1000 ; i++) {
x = Math.floor( Math.random() * 400 ) - 50;
y = Math.floor( Math.random() * 400 ) - 50;
w = Math.floor( Math.random() * 100 );
h = Math.floor( Math.random() * 100 );
ctx.fillStyle = 'rgb(' + Math.floor(Math.random()*256) + ","
+ Math.floor(Math.random()*256) + "," + Math.floor(Math.random()*256) + ')';
ctx.fillRect( x, y, w, h );
}
}
function applyFilter( ctx1, ctx2, x, y ) {
var w = 100, h = 100;
var img = ctx1.getImageData(x, y, w, h);
var pixels = img.data;
var k;
for (k = 0 ; k < pixels.length ; k += 4) {
pixels[k + 0] = 255 - pixels[k + 0];
pixels[k + 1] = 255 - pixels[k + 1];
pixels[k + 2] = 255 - pixels[k + 2];
}
ctx2.putImageData(img, 0, 0);
}
Take attention to the applyFilter function.
Upvotes: 1