Skymen
Skymen

Reputation: 145

Replace a color on canvas

I'm using html5 canvas to make a game. I made a spritefont system to be able to draw text from a texture. Namely

this one.

Now I'd like to be able to change the white part of the text to any color I want. My guess is that I'll need to render the texture to a temporary canvas change the color and get the new texture and draw that instead.

However, I don't know how I can replace a color using the canvas's functions.

And I don't even know if this is the best way to do this. What should I do?

Upvotes: 4

Views: 2164

Answers (2)

AuxTaco
AuxTaco

Reputation: 5181

Since your spritefont is monochrome, you can use CanvasRenderingContext2D's 'multiply' globalCompositeOperation to apply color to the white part. But multiplying by a solid rectangle of color will wipe out the transparency, so you'll need to redraw the transparent parts with 'destination-atop'.

const FONT_COLOR = '#39f';

// Load up your spritefont
const spritefont = new Image();
spritefont.src = 'https://i.sstatic.net/mDvum.png';

// While waiting for the image to load,
// create a canvas to do the coloring work on
const fontCanvas = document.createElement('canvas');
const fontContext = fontCanvas.getContext('2d');

// Once the spritefont is loaded,
spritefont.addEventListener('load', function () {
  // Resize the canvas to match the image's dimensions
  fontCanvas.width = spritefont.width;
  fontCanvas.height = spritefont.height;

  // Draw your image on the canvas with a black background
  // Without the background, you'll get tinting at the partially-transparent edges
  fontContext.fillStyle = 'black';
  fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
  fontContext.drawImage(spritefont, 0, 0);
  
  // Multiply by the font color
  // white * color = color, black * color = black
  fontContext.globalCompositeOperation = 'multiply';
  fontContext.fillStyle = FONT_COLOR;
  fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);

  // Restore the transparency
  fontContext.globalCompositeOperation = 'destination-atop';
  fontContext.drawImage(spritefont, 0, 0);
});

// Display the canvas in the snippet
document.body.append(fontCanvas);
/* just to prove that alpha is preserved */
canvas {background:0 0/32px 32px linear-gradient(45deg,#ccc 25%,transparent 25%,transparent 75%,#ccc 75%,#ccc),16px 16px/32px 32px linear-gradient(45deg,#ccc 25%,#999 25%,#999 75%,#ccc 75%,#ccc);}

If you plan to put the color-changing functionality in a function and reuse the canvas (which you should), make sure to set the context's globalCompositeOperation back to the default, 'source-over'.

Upvotes: 2

Akshay Soam
Akshay Soam

Reputation: 1620

HTML5 canvases follows draw and forget strategy. If you want any change (be it font color or change of shapes or text or lines etc) in what had been drawn earlier, you need to re-draw everything.

Mostly upto to my use of canvases, the whole re-drawing process is pretty fast and works without any lag or delay.

EDIT

context.fillStyle = 'red';
context.strokeStyle = 'black';

context.font = '20pt Verdana';
context.fillText('Some text', 50, 50);
context.strokeText('Some text', 50, 50);

context.fill();
context.stroke();

Upvotes: 0

Related Questions