javascript 如何将 html div 转换为图像,然后另存为 gif 或 png?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23590235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:10:22  来源:igfitidea点击:

How do you convert an html div to image and then save as gif or png?

javascriptjqueryhtmlcss

提问by Bari

I have tried figuring out a multitude of coded div to image methods on stackoverflow and across the internet. The codes aren't working for me, because none of methods are exactly what I need and I'm screwing up the code with my modifications to fit what I need.

我已经尝试在 stackoverflow 和 Internet 上找出大量编码 div 来成像方法。这些代码对我不起作用,因为没有一种方法正是我所需要的,而且我正在通过修改来搞砸代码以适应我的需要。

Anyway, a few minutes ago I found someone who is actually applying the code to divs that are set up like mine. Please take a look at his/her tool (it's what I am doing just with a few more images):

无论如何,几分钟前我发现有人实际上将代码应用于像我一样设置的 div。请看一看他/她的工具(这就是我正在做的,只是多放几张图片):

http://kpomservices.com/html5canvas/indexsucc.html

http://kpomservices.com/html5canvas/indexsucc.html

and his/her blueprint (source file):

和他/她的蓝图(源文件):

view-source:http://kpomservices.com/html5canvas/indexsucc.html

查看源:http: //kpomservices.com/html5canvas/indexsucc.html

This is what I did:

这就是我所做的:

  1. I copied the scripts from the source file (found after </body>tag):

    <script src="js/html2canvas.js"></script> <script src="js/base64.js"></script> <script src="js/canvas2image.js"></script> <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>

  2. I pasted it into my header file above the </head>.

  3. I replaced all src=""with complete urls (they aren't hosted on my servers yet, because I'm testing to see if this will even work for me first).
  4. I copied the function script from http://kpomservices.com/HTML_to_Canvas.php:

    function convert() {
                    dom = document.getElementById('watch');
    
                    // execute the html2canvas script
                    var script,
                    $this = this,
                    options = this.options,
                    runH2c = function(){
                        try {
                            var canvas =     window.html2canvas([ document.getElementById('watch') ], {
                                onrendered: function( canvas ) {
    
                                /*
                                canvas is the actual canvas element,
                                to append it to the page call for example
                                */
                                window.open(canvas.toDataURL());
                                //document.body.appendChild( canvas );
                                }
                            });
                        } catch( e ) {
                            $this.h2cDone = true;
                            log("Error in html2canvas: " + e.message);
                        }
                    };
    
                    if ( window.html2canvas === undefined && script === undefined ) {
                    } else {.
                        // html2canvas already loaded, just run it then
                        runH2c();
                    }
                }
    
  5. I pasted it, as is, between <script></script>tags in the header file.

  6. I replaced both (2) instances document.getElementById('watch')with my div id name: document.getElementById('captme').

  7. I copied and pasted the displaybox styling from the source file and pasted it before the </head>in header file (I also tried adding it to the css file only, but that didn't work, either):

    <style>
    #displaybox {
    z-index: 10000;
    filter: alpha(opacity=50); /*older IE*/
    filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50); /* IE */
    -moz-opacity: .50; /*older Mozilla*/
    -khtml-opacity: 0.5;   /*older Safari*/
    opacity: 0.5;   /*supported by current Mozivalidate-textlla, Safari, and Opera*/
    background-color:#000000;
    position:fixed; top:0px; left:0px; width:100%; height:100%; color:#FFFFFF; text-align:center; vertical-align:middle;
    }
    </style>
    
  1. 我从源文件中复制了脚本(在</body>标签之后找到):

    <script src="js/html2canvas.js"></script> <script src="js/base64.js"></script> <script src="js/canvas2image.js"></script> <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>

  2. 我将它粘贴到</head>.

  3. src=""用完整的 url替换了所有内容(它们还没有托管在我的服务器上,因为我正在测试这是否首先对我有用)。
  4. 我从http://kpomservices.com/HTML_to_Canvas.php复制了函数脚本:

    function convert() {
                    dom = document.getElementById('watch');
    
                    // execute the html2canvas script
                    var script,
                    $this = this,
                    options = this.options,
                    runH2c = function(){
                        try {
                            var canvas =     window.html2canvas([ document.getElementById('watch') ], {
                                onrendered: function( canvas ) {
    
                                /*
                                canvas is the actual canvas element,
                                to append it to the page call for example
                                */
                                window.open(canvas.toDataURL());
                                //document.body.appendChild( canvas );
                                }
                            });
                        } catch( e ) {
                            $this.h2cDone = true;
                            log("Error in html2canvas: " + e.message);
                        }
                    };
    
                    if ( window.html2canvas === undefined && script === undefined ) {
                    } else {.
                        // html2canvas already loaded, just run it then
                        runH2c();
                    }
                }
    
  5. 我按原样粘贴<script></script>在头文件中的标签之间。

  6. 我换成两(2)情况下,document.getElementById('watch')用我的DIV ID名称: document.getElementById('captme')

  7. 我从源文件中复制并粘贴了显示框样式,并将其粘贴到</head>in 头文件之前(我也尝试仅将其添加到 css 文件中,但这也不起作用):

    <style>
    #displaybox {
    z-index: 10000;
    filter: alpha(opacity=50); /*older IE*/
    filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50); /* IE */
    -moz-opacity: .50; /*older Mozilla*/
    -khtml-opacity: 0.5;   /*older Safari*/
    opacity: 0.5;   /*supported by current Mozivalidate-textlla, Safari, and Opera*/
    background-color:#000000;
    position:fixed; top:0px; left:0px; width:100%; height:100%; color:#FFFFFF; text-align:center; vertical-align:middle;
    }
    </style>
    

8) I copied and pasted just these two lines from the source file (I don't need the other two buttons) into the index file after <?php get_header(); ?>:

8)我将源文件中的这两行(我不需要其他两个按钮)复制并粘贴到索引文件中<?php get_header(); ?>

<div id="displaybox" style="display: none;"></div>
<input type="button" value="View As Image" onClick="javascript:return convert();">

9) I copied and pasted this line from the source file into the index file after the <div id="captme">:

9)我将此行从源文件复制并粘贴到索引文件中<div id="captme">

<canvas id="localcanvas" style="display:none" width=500 height=500></canvas>

10) All that and nothing works. I can click on the button but it renders nothing.

10)所有这些都不起作用。我可以点击按钮,但它什么都不渲染。

What went wrong? Thanks for any guidance you share!

什么地方出了错?感谢您分享的任何指导!

回答by user3359391

This is working for me. It renders picture from div solnePuzzle and post to PHP script via ajax post. In PHP script save.php, I base_64 decode and save content via file_put_content to img.

这对我有用。它从 div solnePuzzle 渲染图片并通过 ajax post 发布到 PHP 脚本。在 PHP 脚本 save.php 中,我 base_64 解码并通过 file_put_content 将内容保存到 img。

html2canvas js

html2canvas js

function capture() {
    $("#solnePuzzle").html2canvas({
        onrendered: function (e) {
            $("#img_val").val(e.toDataURL("image/png"));
            var t = $("#myForm").serializeArray();
            $.ajax({
                url: "save.php",
                type: "POST",
                dataType: "json",
                data: {
                    box: box,
                    form: t
                },
                success: function (e) {
                    alert(e.text)
                }
            })
        }
    })
}

回答by Krishna pattar

http://jsfiddle.net/8ypxW/3/

http://jsfiddle.net/8ypxW/3/

$(function() { 
    $("#btnSave").click(function() { 
        html2canvas($("#widget"), {
            onrendered: function(canvas) {
                theCanvas = canvas;
                document.body.appendChild(canvas);

                // Convert and download as image 
                Canvas2Image.saveAsPNG(canvas); 
                $("#img-out").append(canvas);
                // Clean up 
                //document.body.removeChild(canvas);
            }
        });
    });
}); 
body {
    font-family: "Lucida Grande", "Lucida Sans", Arial, sans-serif;
    font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;

}

.dataset {
    float: left;
    vertical-align: top;


}

.widget {
    display: inline-block;
    background-color: white;
    font-size: 14px !important;
    line-height: 20px !important;

    margin: 5px;
    vertical-align: top;
    color: #333;

    border-radius: 5px;
    margin: 10px;
    padding-bottom: 20px;
    border: 1px solid lightgray;


    border-radius:5px;
    -webkit-border-radius: 5px;


    display: inline-block;
    page-break-after: always;

}

.widget .header p {
   padding: 10px;
   border-bottom: 1px solid lightgrey;
   max-width: 360px;
}

.widget .header .title {
    font-weight: bold;
    vertical-align: middle;
    min-height: 36px;
    padding: 5px 10px 5px 10px;

}

.widget .header:hover {
    background-color: #f4f4f4;
}

.widget .header  .title.selected {
    border-color: cornflowerblue;
    background-color: #EEF;

}

.widget .content {
    padding: 5px;
    overflow-y: auto;
    max-height: 400px;
}

.autolayout {
    display: inline-block;
}

.element {
    width: 360px;
}

.compact .content {
    display: table;
    width: 100%;
}

.compact .row {
    display: table-row;
    width: 100%;
}

.compact .cell {
    display: table-cell;
}

.compact .row.selected {
    background-color: #eee;
}



.toolbar {
    display: block;
    vertical-align: top;
    margin: 10px;
}

.toolbar .basis {
    min-width: 100px;
}

.btn {
    /*min-width: 60px;*/
}


.cell.value {
    overflow: hidden;
    text-wrap: none;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: right;
    padding-right: 10px;
}

.cell.freq {
    width: 60px;
}

.cell.glyph {
    vertical-align: middle;
    width: 100px;
}


.element {

}
.element table {
    table-layout: fixed;
    width: 100%;
}

.element td {
    padding: 0px;

}

.element .selectable:hover {
    background-color: #f4f4f4;
}


.element .stat {
    text-align: right;
    padding-right: 20px;
    font-weigth: bold;
    color: darkgray;
}



.element .bar {
    height: 18px;
    display: inline-block;
    float: left;
}
.bar-both {
    background-color: #0a67a3 !important;

}

.bar-fg {
    background-color: #3e97d1 !important;
}

.bar-bg {
    background-color: #ddd !important;
}

.selected .bar-fg {
    background-color: #FC0;
}

.selected .bar-both  {
    background-color:#FA0;
}

tr.selected {
    background-color: #eee;
}

.crosstab .selectable:hover {
    background-color: #f4f4f4;
}

.crosstab tr.selected {
    background-color: #eee;
}

.crosstab .header p {
    max-width: 600px;
}


.crosstab td {
  padding: 0 5px 0 5px;
  text-align: right;
}

.crosstab td.value {
  min-width: 60px;
  max-width: 240px;
  text-align: left;
}

.crosstab .cell {
    vertical-align: top;
}



.crosstab th.cell {
    max-width: 120px;
    overflow: hidden;
    white-space: normal;
    text-overflow: ellipsis;
    text-align: right;
    padding-right: 10px;
    vertical-align: bottom;
}

.crosstab .n {
    color: darkgray;
}
.fieldlist {
}

.constraints {
    min-width:300px;
    padding: 10px;

    border-radius:5px;
    -webkit-border-radius: 5px;


}
.constraints table {
    width: 100%;

}

.sidenote {
  max-width:300px;
  padding: 0 10px 0px 10px;
  display: inline-block;
  vertical-align: top;
}

.headnote {
    max-width: 600px;
    padding: 10px;
    margin: 10px;
    display: inline-block;
}

.info-block {
    /*border: 1px solid lightgrey;*/
    background-color: #eee;
    vertical-align: top;
    margin: 10px;
    padding: 10px;
    display: block;

    /*box-shadow: 0 0 0 0px #9bc0cf, 0 0 0 3px #e0ebf0;*/
}

.menu-item {
}

.menu-item-value {
    text-align: right;
    float: right;
}

.gradient-blue {
    background: #b8e1fc; /* Old browsers */
    /* IE9 SVG, needs conditional override of 'filter' to 'none' */
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2I4ZTFmYyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwJSIgc3RvcC1jb2xvcj0iI2E5ZDJmMyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjI1JSIgc3RvcC1jb2xvcj0iIzkwYmFlNCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjM3JSIgc3RvcC1jb2xvcj0iIzkwYmNlYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzkwYmZmMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUxJSIgc3RvcC1jb2xvcj0iIzZiYThlNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjgzJSIgc3RvcC1jb2xvcj0iI2EyZGFmNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNiZGYzZmQiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b8e1fc), color-stop(10%, #a9d2f3), color-stop(25%, #90bae4), color-stop(37%, #90bcea), color-stop(50%, #90bff0), color-stop(51%, #6ba8e5), color-stop(83%, #a2daf5), color-stop(100%, #bdf3fd)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%); /* IE10+ */
    background: linear-gradient(to bottom, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b8e1fc', endColorstr='#bdf3fd', GradientType=0); /* IE6-8 */
}
<span id="widget" class="widget" field="AGE" roundby="20" description="Patient age, in years">
    <div class="header ng-scope">
      <div class="title ng-binding">AGE</div>
      <p class="ng-binding">Patient age, in years</p>
    </div>
    <div class="element ng-scope">
      <div ng-show="hasData()" class="content">
        <table ng-model="table" class="ng-pristine ng-valid">
          <colgroup>
            <col/>
            <col width="60x"/>
            <col width="100px"/>
          </colgroup>
          <thead>
            <tr>
              <th class="cell value">Value</th>
              <th class="cell freq">Freq</th>
              <th class="cell value"></th>
            </tr>
          </thead>
          <tbody>
<tr ng-repeat="rowKey in table.rowKeys | orderBy:elementRowSort " ng-click="onSelect(rowKey, $event.shiftKey)" ng-class="{true:'selected'}[isSelected(rowKey)]" data-key="0" class="selectable ng-scope">
            <td class="cell value"><span tooltip="0 to 19" class="ng-scope ng-binding">0 to 19</span>
            </td>

            <td class="cell freq ng-binding">17.2%</td>
            <td class="cell glyph">
              <span class="bar bar-both" ng-style="{width: (table.getBothPct(rowKey) | barSize)+'%' }" style="width: 17.234468937875754%;"></span>
              <span class="bar bar-fg" ng-style="{width: (table.getFgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
              <span class="bar bar-bg" ng-style="{width: (table.getBgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
            </td>
          </tr><tr ng-repeat="rowKey in table.rowKeys | orderBy:elementRowSort " ng-click="onSelect(rowKey, $event.shiftKey)" ng-class="{true:'selected'}[isSelected(rowKey)]" data-key="20" class="selectable ng-scope">
            <td class="cell value"><span tooltip="20 to 39" class="ng-scope ng-binding">20 to 39</span>
            </td>
            <td class="cell freq ng-binding">18.0%</td>
            <td class="cell glyph">
              <span class="bar bar-both" ng-style="{width: (table.getBothPct(rowKey) | barSize)+'%' }" style="width: 18.03607214428858%;"></span>
              <span class="bar bar-fg" ng-style="{width: (table.getFgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
              <span class="bar bar-bg" ng-style="{width: (table.getBgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
            </td>
          </tr><!-- end ngRepeat: rowKey in table.rowKeys | orderBy:elementRowSort --><tr ng-repeat="rowKey in table.rowKeys | orderBy:elementRowSort " ng-click="onSelect(rowKey, $event.shiftKey)" ng-class="{true:'selected'}[isSelected(rowKey)]" data-key="40" class="selectable ng-scope">
            <td class="cell value"><span tooltip="40 to 59" class="ng-scope ng-binding">40 to 59</span>
            </td>

            <!--<td >{{table.getRowPercent('current', rowKey) | percent}}</td>-->
            <td class="cell freq ng-binding">34.3%</td>
            <td class="cell glyph">
              <!--<div class="bar bar-both" style="width: {{(row.current.pct * 100)||2}}px; " ></div>-->
              <span class="bar bar-both" ng-style="{width: (table.getBothPct(rowKey) | barSize)+'%' }" style="width: 34.2685370741483%;"></span>
              <span class="bar bar-fg" ng-style="{width: (table.getFgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
              <span class="bar bar-bg" ng-style="{width: (table.getBgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
            </td>
          </tr><!-- end ngRepeat: rowKey in table.rowKeys | orderBy:elementRowSort --><tr ng-repeat="rowKey in table.rowKeys | orderBy:elementRowSort " ng-click="onSelect(rowKey, $event.shiftKey)" ng-class="{true:'selected'}[isSelected(rowKey)]" data-key="60" class="selectable ng-scope">
            <td class="cell value"><span tooltip="60 to 79" class="ng-scope ng-binding">60 to 79</span>
            </td>

            <!--<td >{{table.getRowPercent('current', rowKey) | percent}}</td>-->
            <td class="cell freq ng-binding">24.0%</td>
            <td class="cell glyph">
              <!--<div class="bar bar-both" style="width: {{(row.current.pct * 100)||2}}px; " ></div>-->
              <span class="bar bar-both" ng-style="{width: (table.getBothPct(rowKey) | barSize)+'%' }" style="width: 24.04809619238477%;"></span>
              <span class="bar bar-fg" ng-style="{width: (table.getFgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
              <span class="bar bar-bg" ng-style="{width: (table.getBgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
            </td>
          </tr><!-- end ngRepeat: rowKey in table.rowKeys | orderBy:elementRowSort --><tr ng-repeat="rowKey in table.rowKeys | orderBy:elementRowSort " ng-click="onSelect(rowKey, $event.shiftKey)" ng-class="{true:'selected'}[isSelected(rowKey)]" data-key="80" class="selectable ng-scope">
            <td class="cell value"><span tooltip="80 to 99" class="ng-scope ng-binding">80 to 99</span>
            </td>

            <!--<td >{{table.getRowPercent('current', rowKey) | percent}}</td>-->
            <td class="cell freq ng-binding">6.4%</td>
            <td class="cell glyph">
              <!--<div class="bar bar-both" style="width: {{(row.current.pct * 100)||2}}px; " ></div>-->
              <span class="bar bar-both" ng-style="{width: (table.getBothPct(rowKey) | barSize)+'%' }" style="width: 6.4128256513026045%;"></span>
              <span class="bar bar-fg" ng-style="{width: (table.getFgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
              <span class="bar bar-bg" ng-style="{width: (table.getBgPct(rowKey) | barSize) +'%' }" style="width: 0%;"></span>
            </td>
          </tr><!-- end ngRepeat: rowKey in table.rowKeys | orderBy:elementRowSort -->
          <tr ng-show="getShowMean()" class="">
            <td class="stat">Mean</td>
            <td class="ng-binding">46.1</td>
          </tr>


          </tbody>
        </table>
      </div>


    </div>
  <!-- ngRepeat: field in getChildren(field) -->
</span>
<br/>
<input type="button" id="btnSave" value="Save PNG"/>

<div id="img-out"></div>