Is it possible to make a gradient-transparent/layer masking image using canvas?

后端 未结 5 1898
傲寒
傲寒 2021-02-05 14:01

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

5条回答
  •  有刺的猬
    2021-02-05 14:33

    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();

提交回复
热议问题