Простое решение: используйте второй холст.
(async () => {
const [ cat, star, hex ] = await Promise.all( loadImages( [ "kNpEG.jpg", "PPfrd.png", "Vcc8C.png" ], 'https://i.stack.imgur.com/' ) );
// the visible canvas
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
// create an offcreen copy
const canvas2 = canvas.cloneNode();
const ctx2 = canvas2.getContext( '2d' );
// on the visible canvas
// we can apply simply the first step source-over operation
ctx.drawImage( cat, 0, 0 );
ctx.drawImage( star, 0, 0 );
// on the offsreen canvas we apply the color blending
ctx2.fillStyle = "red";
ctx2.fillRect( 0, 0, 200, 200 );
ctx2.globalCompositeOperation = "destination-in";
ctx2.drawImage( hex, 0, 0 );
// now we can draw it on the visible canvas, still as source-over
ctx.drawImage( canvas2, 0, 0 );
})().catch( console.error );
function loadImages( filenames, path = "" ) {
return filenames.map( filename => new Promise( (res, rej ) => {
const img = new Image();
img.onload = (evt) => res( img );
img.onerror = rej;
img.src = path + filename;
} ) );
}
<canvas id="canvas" width="200" height="200"></canvas>
Не всегда возможно: рисовать спереди назад.
(async () => {
const [ cat, star, hex ] = await Promise.all( loadImages( [ "kNpEG.jpg", "PPfrd.png", "Vcc8C.png" ], 'https://i.stack.imgur.com/' ) );
// the only canvas
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
// we start with the color blending
ctx.fillStyle = "red";
ctx.fillRect( 0, 0, 200, 200 );
ctx.globalCompositeOperation = "destination-in";
ctx.drawImage( hex, 0, 0 );
// and now we draw from behind
ctx.globalCompositeOperation = "destination-over";
// so we need to inverse these two
ctx.drawImage( star, 0, 0 );
ctx.drawImage( cat, 0, 0 );
})().catch( console.error );
function loadImages( filenames, path = "" ) {
return filenames.map( filename => new Promise( (res, rej ) => {
const img = new Image();
img.onload = (evt) => res( img );
img.onerror = rej;
img.src = path + filename;
} ) );
}
<canvas id="canvas" width="200" height="200"></canvas>