Reputation: 214
Here's the result I want to realize.As is shown, the QR Code consists of black and white , but I want the black part to be transparent so as to blend with the background outside. The background outside may change, it's not always green.
I've tried to use background blend mode with CSS like this:
background-image: url('');
background-color: rgba(0,0,0,0);
background-blend-mode: screen;
It does nothing.
Thx for help.
Upvotes: 3
Views: 2160
Reputation: 1156
You can actually achieve this effect through canvas pixel manipulation, but as other users have stated it would be simpler to make your image transparent through an image editing program.
I have created an example of how to achieve this in the fiddle here.
What this code first does is retrieve the image element <img id="code" src="url.png">
, construct a canvas object and draw the contents of the image into the canvas through the context.drawImage
call.
// Get the image element.
var el = document.getElementById('code');
// Create a canvas and set its width and height.
var canvas = document.createElement('canvas');
canvas.setAttribute('width', 250);
canvas.setAttribute('height', 250);
// Get the canvas drawing context, and draw the image to it.
var context = canvas.getContext('2d');
context.drawImage(el, 0, 0, canvas.width, canvas.height);
Next,
// Get the canvas image data.
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
// Create a function for preserving a specified colour.
var preserveColor = function(imageData, color) {
// Get the pixel data from the source.
var data = imageData.data;
// Iterate through all the pixels.
for (var i = 0; i < data.length; i += 4) {
// Check if the current pixel should have preserved transparency. This simply compares whether the color we passed in is equivalent to our pixel data.
var preserve = data[i] === color.r
&& data[i + 1] === color.g
&& data[i + 2] === color.b
&& data[i + 3] === color.a;
// Either preserve the initial transparency or set the transparency to 0.
data[i + 3] = preserve ? data[i + 3] : 0;
}
return imageData;
};
// Get the new pixel data and set it to the canvas context.
var newData = preserveColor(imageData, {r: 255, g: 255, b: 255, a: 255});
context.putImageData(newData, 0, 0);
Finally, we add the element to our page using document.body.appendChild(canvas);
. You can alternatively completely replace the original image element with the canvas.
Obviously, this isn't an ideal solution because iterating through pixel data can be very slow and only increases with large image sizes. You could also easily change the preserveColor
function to instead do the opposite with makeTransparent
where the color specified becomes transparent. However, this would require a bit more logic for colors that are similar to the one you specify. Alternatively, you could implement this as a shader so that the processing is more efficient by shifting it to the GPU instead of the CPU.
Upvotes: 1
Reputation: 1522
You have the correct blend mode, and I assume the background-image url is omitted on purpose, so the first reason I would resort to is browser compatibility. For this, take a look at the compatibility chart on caniuse.com, for example.
I'd suggest using a transparent PNG here, as that's exactly what it's indended for. Even if you get background-blend-mode
to work, unless the background is perfectly black (meaning #000) - looking at your example image, that isn't the case, so you wouldn't get the effect you want one way or the other.
Another issue I can think of here is that you probably want that QR code as in img
element, for the following reasons:
Upvotes: 1