【问题标题】:Dropshadow in html canvas using context.putImageData使用 context.putImageData 在 html 画布中投影
【发布时间】:2019-03-14 23:13:39
【问题描述】:

在 html 画布中,我试图在其中包含透明片段的图像上生成阴影。此图像由代码生成,然后使用:ctx.putImageData(dst, 0, 0);

绘制到画布上

问题是下面的代码没有产生任何阴影:

ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 15;
ctx.shadowColor = 'rgba(0,0,0,1)';

ctx.putImageData(dst, 0, 0);

任何帮助将不胜感激

【问题讨论】:

    标签: html canvas html5-canvas dropshadow putimagedata


    【解决方案1】:

    ctx.putImageData() 会将上下文中的像素替换为您放置的 ImageData 中包含的像素。
    没有像 shadowBlur 这样的上下文属性,也没有过滤器,也没有 globalCompositeOperation,甚至没有会影响它的矩阵变换。即使是 ImageData 中的透明像素在上下文中也是透明的。

    const ctx = canvas.getContext('2d');
    ctx.fillStyle = 'salmon';
    ctx.fillRect(0,0,300,150);
    
    ctx.translate(120, 50);
    ctx.rotate(Math.PI/3);
    ctx.translate(-25, -25);
    ctx.filter = 'blur(5px)';
    ctx.globalCompositeOperation = 'lighter';
    
    ctx.fillStyle = '#0000FF';
    ctx.fillRect(0,0,50,50);
    
    setTimeout(() => {
      // at this time, all previous filters, transform, gCO are still active 
      const bluerect = ctx.createImageData(50,50);
      const data = new Uint32Array(bluerect.data.buffer);
      data.fill(0xFFFF0000); // blue
      ctx.putImageData(bluerect, 0, 0); // same as our previous fillRect();
      // a transparent ImageData (smaller)
      const transrect = ctx.createImageData(25, 25);
      ctx.putImageData(transrect, 170, 50); // push a bit farther;
    }, 1500);
    body {
      background: lightblue;
    }
    <canvas id="canvas"></canvas>

    那么,如何处理 ImageData 并且仍然能够在其上应用上下文的属性? 浏览第二个屏幕外画布,您将在其上放置 ImageData,然后您将在主画布上进行绘制。 drawImage 接受一个 HTMLCanvasElement 作为源,它受 shadowBlur 等上下文属性的影响:

    const ctx = canvas.getContext('2d');
    ctx.shadowBlur = 12;
    ctx.shadowColor = "red";
    // our ImageData
    const bluerect = ctx.createImageData(50,50);
    const data = new Uint32Array(bluerect.data.buffer);
    data.fill(0xFFFF0000); // blue
    // create a new canvas, the size of our ImageData
    const offscreen = document.createElement('canvas');
    offscreen.width = bluerect.width;
    offscreen.height = bluerect.height;
    // put our ImageData on it
    offscreen.getContext('2d')
      .putImageData(bluerect, 0, 0);
    // draw it on main canvas
    ctx.drawImage(offscreen, 50, 50);
    <canvas id="canvas"></canvas>

    现在,新浏览器也可以通过从 ImageData 生成 ImageBitmap 来在不使用第二个浏览器的情况下执行此操作,但此操作是异步的,因此您可能仍然更喜欢旧方式。

    const ctx = canvas.getContext('2d');
    ctx.shadowBlur = 12;
    ctx.shadowColor = "red";
    // our ImageData
    const bluerect = ctx.createImageData(50,50);
    const data = new Uint32Array(bluerect.data.buffer);
    data.fill(0xFFFF0000); // blue
    
    // create an ImageBitmap from our ImageData
    createImageBitmap(bluerect)
    .then(bitmap => { // later
      ctx.drawImage(bitmap, 50, 50);
    });
    <canvas id="canvas"></canvas>

    【讨论】:

    • 优秀的答案,我使用了您的第二个代码 sn-p,它运行良好!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2017-07-22
    • 2015-02-10
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    相关资源
    最近更新 更多