Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 772
Skymen Avatar asked Oct 15 '25 14:10

Skymen


1 Answers

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'.

like image 173
AuxTaco Avatar answered Oct 18 '25 06:10

AuxTaco



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!