Ragnaraxis
Ragnaraxis

Reputation: 352

HTML Canvas composition: combining "lighter" and "source-atop" effects

Essentially, I have a gray-scale image of a cube that I would like to color different colors using an HTML 5 canvas. I don't care much about browser compatibility at the moment, so I've been looking at the globalCompositeOperation property values listed here:

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

Essentially, I want to combine the effects of "source-atop" and "lighter". Using just source-atop, I get a blue shape, but the different shades of gray are all filled in with the same shade of blue, so I get a flat, skewed hexagon instead of a cube.

Using just the lighter composite option, I get closer to the effect I want. All the cube faces are differing shades of blue like I want, but the previously transparent background becomes solid blue.

I would love a canvas solution that would produce the cube in the lighter example without the blue background. I realize I could just define the cube's points and use the fill style and paths to create the cube, but I have plans to use more complex icon shapes than a cube, and I don't want to do all that when I already have a gray-scale .png ready unless I absolutely have to.

Code currently is pretty basic

var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext("2d");
var cube = new Image();
cube.src = "url" //path to gray-scale cube image.

ctx.clearRect(0, 0, canvas.width, canvaseheight);
ctx.drawImage(cube, 0, 0);
ctx.globalCompositeOperation = "lighter"; //or "source-atop"
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);

Upvotes: 0

Views: 923

Answers (1)

Ragnaraxis
Ragnaraxis

Reputation: 352

Turns out you can combine them pretty easily. Here is how I ended up accomplishing this task.

var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext("2d");
var cube = new Image();
cube.src = "url" //path to gray-scale cube image.

//get a blue mask that fills the entire cube region
ctx.clearRect(0, 0, canvas.width, canvaseheight);
ctx.drawImage(cube, 0, 0);
ctx.globalCompositeOperation = "source-atop";
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);

//save that image off somewhere.
var blueMask = new Image();
blueMask.src = canvas.toDataURL();

ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.globalCompositeOperation = "source-over";

//draw the cube again
ctx.drawImage(cube, 0,0);

//draw the mask image over it with the 'lighter' composition setting.
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(blueMask, 0, 0);

This produces the desired result.

Upvotes: 0

Related Questions