【问题标题】:Export DIV to JPG/PNG - html2canvas doesnt work将 DIV 导出为 JPG/PNG - html2canvas 不起作用
【发布时间】:2016-02-27 13:29:20
【问题描述】:

我创建了一种徽标生成器,它使用自定义 css 样式创建 div。我想添加按钮“下载”以让用户将其作为 png/jpg 文件获取。

我浏览了有关 stackoverflow 的所有其他帖子,但它们对我不起作用。我尝试了 html2canvas 但这并没有给出预期的结果。

我的 div:

<i id="icon" class="fa fa-android" style="text-shadow: rgb(48, 117, 165) 0px 0px, rgb(48, 118, 167) 1px 1px, rgb(49, 120, 169) 2px 2px, rgb(49, 121, 171) 3px 3px, rgb(50, 123, 173) 4px 4px, rgb(51, 124, 175) 5px 5px, rgb(51, 125, 177) 6px 6px, rgb(52, 127, 179) 7px 7px, rgb(52, 128, 181) 8px 8px, rgb(53, 130, 183) 9px 9px, rgb(53, 131, 185) 10px 10px, rgb(54, 133, 187) 11px 11px, rgb(55, 134, 189) 12px 12px, rgb(55, 136, 191) 13px 13px, rgb(56, 137, 193) 14px 14px, rgb(56, 138, 195) 15px 15px, rgb(57, 140, 197) 16px 16px, rgb(58, 141, 199) 17px 17px, rgb(58, 143, 201) 18px 18px, rgb(59, 144, 203) 19px 19px, rgb(59, 146, 205) 20px 20px, rgb(60, 147, 207) 21px 21px, rgb(60, 148, 209) 22px 22px, rgb(61, 150, 211) 23px 23px, rgb(62, 151, 213) 24px 24px, rgb(62, 153, 215) 25px 25px, rgb(63, 154, 217) 26px 26px, rgb(63, 156, 219) 27px 27px, rgb(64, 157, 221) 28px 28px, rgb(65, 158, 223) 29px 29px, rgb(65, 160, 225) 30px 30px, rgb(66, 161, 227) 31px 31px, rgb(66, 163, 229) 32px 32px, rgb(67, 164, 231) 33px 33px, rgb(67, 166, 233) 34px 34px; font-size: 80px; color: white; height: 150px; width: 150px; line-height: 150px; border-radius: 0%; text-align: center; background-color: rgb(68, 167, 235);"></i>

看起来像:

虽然画布创建:

根据文档,一些 CSS 可能不受支持,我担心这就是我的情况。还有其他方法可以将此 DIV 保存为图片吗?

【问题讨论】:

    标签: javascript css canvas html5-canvas html2canvas


    【解决方案1】:

    html2canvas 似乎不允许多个文本阴影,但您可以使用本机画布命令获得类似的效果。

    您可以在画布上绘制定向阴影(如运动模糊)。

    1. 在第二个(内存画布)上,获取图像在阴影方向的轮廓。

      • 绘制在阴影方向偏移几个像素的图像。

      • 使用destination-out 合成擦除原始图像。这只会留下只有几个像素宽的阴影轮廓。

    2. 在第三个画布上,以不断增加的偏移量重复绘制阴影。这会创建完整的阴影(但它目前是完全不透明的——不是渐变)。

    3. 在主画布上填充一个渐变,从图像 [x,y] 开始,并延伸到图像之外,略小于阴影长度。

    4. 使用source-in 合成将阴影从第三个画布绘制到主画布上。合成会导致使用渐变绘制阴影。

    5. 在阴影上绘制原始图像。

    6. 使用destination-over 合成在阴影图像“下方”绘制背景。

    7. 完成 - 你有一个带有尾随阴影的图像

    这是示例代码和演示:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    var c=document.createElement('canvas');
    cctx=c.getContext('2d');
    var cc=document.createElement('canvas');
    ccctx=cc.getContext('2d');
    c.width=cc.width=cw;
    c.height=cc.height=ch;
    
    // x,y of the image
    var x=50;
    var y=50;
    
    // shadowing definition variables
    var offsetX=2;
    var offsetY=2;
    var extent=50;
    
    var img=new Image();
    img.onload=start;
    img.src="https://dl.dropboxusercontent.com/u/139992952/multple/android.png";
    function start(){
    
      // get the offset outline of the image on a second 
      // by drawing the image offset by a few pixels
      // and then erasing the un-offset image
      // which leaves just the "shadow" outline
      cctx.drawImage(img,x+offsetX,y+offsetY);
      cctx.globalCompositeOperation='destination-out';
      cctx.drawImage(img,x,y);
      cctx.drawImage(img,x,y);
      cctx.drawImage(img,x,y);    
      cctx.globalCompositeOperation='source-atop';
      cctx.fillStyle='black';
      cctx.fillRect(0,0,cw,ch);
    
      // draw the "shadow" canvas repeatedly 
      // with an increasing offset onto another canvas
      for(var i=0;i<extent;i++){
        ccctx.drawImage(c,i,i)
      }
    
      // create a gradient on the main canvas
      // going from the image x,y and extending past the image 
      // by a bit less than the shadow length
      var g=ctx.createLinearGradient(x,y,x+img.width+extent*.75,y+img.height+extent*.75);
      g.addColorStop(0.00,'rgba(0,0,0,0.50)');
      g.addColorStop(0.75,'rgba(0,0,0,.10)');
      g.addColorStop(1.00,'rgba(0,0,0,0)');
      ctx.fillStyle=g;
      ctx.fillRect(0,0,cw,ch);
    
      // draw the extended shadow from the 3rd canvas onto
      // the main canvas with 'source-in' compositing so
      // the shadow is made gradient
      ctx.globalCompositeOperation='source-in';
      ctx.drawImage(cc,0,0);
    
      // draw the original image over the shadow
      // the original image is now shadowed
      ctx.globalCompositeOperation='source-over';
      ctx.drawImage(img,x,y);
    
      // draw the background "under" the shadowed image
      // using 'destination-over' compositing
      ctx.globalCompositeOperation='destination-over';
      ctx.fillStyle='#44A7EB';
      ctx.fillRect(0,0,cw,ch);
    }
    body{ background-color: ivory; }
    canvas{border:1px solid red; margin:0 auto; }
    &lt;canvas id="canvas" width=400 height=400&gt;&lt;/canvas&gt;

    或者,您可以通过重复绘制具有不同不透明度的图像来创建运动模糊效果。

    示例代码和演示

    警告:示例代码具有硬编码值——需要调整!

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    
    var image=new Image();
    image.onload=start;
    image.src="https://dl.dropboxusercontent.com/u/139992952/multple/android.png";
    function start(){
      var c=document.createElement('canvas');
      var cctx=c.getContext('2d');
      c.width=image.width;
      c.height=image.height;
      cctx.translate(c.width/2,c.height/2);
      cctx.rotate(Math.PI/4);
      cctx.drawImage(image,-image.width/2,-image.height/2);
      cctx.setTransform(1,0,0,1,0,0);
      cctx.globalCompositeOperation='source-atop';
      cctx.fillRect(0,0,c.width,c.height);
    
      ctx.translate(-50,0);
      ctx.translate(100,200);
      ctx.rotate(-Math.PI/4);
      ctx.clearRect(0,0,canvas.width,canvas.height)   
      var y=0;
      while (++y <= 100) {
        ctx.globalAlpha=1/y;
        ctx.drawImage(c, 0,0, image.width, image.height+y);
      }
      ctx.globalAlpha=1;
      ctx.setTransform(1,0,0,1,0,0);
      ctx.drawImage(image,96.5,87.5);
    
      ctx.globalCompositeOperation='destination-over';
      ctx.fillStyle='#44A7EB';
      ctx.fillRect(0,0,cw,ch);  
    }
    body{ background-color: ivory; }
    canvas{border:1px solid red; margin:0 auto; }
    &lt;canvas id="canvas" width=500 height=400&gt;&lt;/canvas&gt;

    【讨论】:

    • 不错的解决方法,但这不会满足 OP 的要求:“将此 DIV 保存为图片”。但我想除了“拍快照”、“拍照”或“使用some experimental features available to extensions in only one browser”之外别无他法。
    • @Kaiido。是的,这些变通办法不是很好的通用解决方案。 AFAIK,在画布上重新创建 div+css,然后执行.toDataURL 是保存 div 内容的唯一跨浏览器方式——而且 CSS 的发展速度比 html2canvas 之类的库更快。您可以使用 PhantomJS 无头浏览器等基于服务器的解决方案来完成这项工作。干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2022-07-22
    • 2017-12-01
    相关资源
    最近更新 更多