I\'ve been following the lessons about transparency and gradients on the Mozilla site: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_an
I have modernized Alnitak's response by incorporating asynchronous loading of the images.
I also got rid of magic numbers.
const imageUrls = [
// Base image
'http://www.netstate.com/states/symb/flowers/images/apple_blossoms.jpg',
// Gradient image
'http://www.netstate.com/states/symb/flowers/images/oklahoma_rose.jpg'
];
const main = async () => {
const ctx = document.getElementById('cv').getContext('2d'),
baseImg = await loadImage(imageUrls[0]),
gradImg = await loadImage(imageUrls[1]);
draw(ctx, baseImg, gradImg);
};
/**
* Loads an Image object via a Promise.
* @param {String} url - Location of an image file
* @return {Promise} Returns a promise that resolves to an Image.
*/
const loadImage = (url) => new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', reject);
img.src = url;
});
/**
* Draws an image, as a gradient applied to it, above another image.
* @param {Image} baseImg - Image that is applied under the gradient
* @param {Image} gradImg - Image to be applied as a gradient
*/
const draw = (ctx, baseImg, gradImg) => {
const {width, height} = baseImg,
originX = Math.floor(width / 2),
originY = Math.floor(height / 2),
radius = Math.min(originX, originY);
const offScreen = document.createElement('canvas');
offScreen.width = offScreen.height = width;
const ctx2 = offScreen.getContext('2d');
ctx2.drawImage(gradImg, 0, 0, width, height);
const gradient = ctx2.createRadialGradient(originX, originY, 0, originX, originY, radius);
gradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
gradient.addColorStop(1, 'rgba(255, 255, 255, 1)');
ctx2.fillStyle = gradient;
ctx2.globalCompositeOperation = 'destination-out';
ctx2.fillRect(0, 0, width, height);
ctx.drawImage(baseImg, 0, 0, width, height);
ctx.drawImage(offScreen, 0, 0, width, height);
};
main();