html2canvas截图生成图片并保存到本地的解决方案

html2canvas是一款JavaScript插件,能够将网页上的HTML元素转化为Canvas对象,从而可以将网页截图输出为图片或者PDF文件。
它的原理是通过遍历DOM树,将每一个HTML元素转化为Canvas对象,并叠加到一起形成一张完整的图片或者PDF文件。在转化过程中,html2canvas还需要解决一些问题,例如处理CSS属性、特殊元素、浏览器兼容性问题等。
html2canvas的原理并不复杂,但是它在实现网页截图这一功能上起到了重要作用,为网页开发、界面设计等领域提供了便利。

一、构建HTML容器

<div id="print-box">
    <div class="print-bg"><img src="images/main.jpg" alt="" width="800"></div>
    <div class="print-content">
        <p style="margin-top: 60px;"><span class="com_name">漏刻有时</span></p>
        <p style="font-size: 24px;">开展 <img src="images/adi.png" alt="" height="30"> 抖音直播销售服务,本公司保证所售产品均为品牌正品。</p>
        <p style="font-size: 24px;"><label style="font-weight: bold;">授权期限:</label>2023年8月8日至2024年8月7日</p>
        <p style="text-align: right;padding-right: 50px;margin-top: 180px;font-size: 20px;">宁波漏刻文化科技有限公司</p>
        <p style="text-align: right;padding-right: 50px;font-size: 20px;">2023年8月8日</p>
    </div>
</div>
<div id="non-print">非打印区域</div>
<button id="btn" onclick="printDiv()">打印</button>
<button id="shotbtn">截图</button>

二、html2canvas截图封装函数

 /* 点击截图按钮事件 */
    $('#shotbtn').click(function () {
        PrtScn("#print-box").then((result) => {
            download(result);
        });
    });

    /* 截图核心方法封装,获取base64 */
    function PrtScn(domName) {
        //console.log(domName);
        if (null == domName || '' == domName) {
            throw ('dom name should not be null');
        }

        if ('#' != domName.charAt(0) && '.' != domName.charAt(0)) {
            throw ('dom element only supports id or class');
        }

        let domIsNull = null;
        switch (domName.charAt(0)) {
            case '#':
                domIsNull = document.getElementById(domName.substr(1));
                break;
            case '.':
                domIsNull = document.getElementsByClassName(domName.substr(1))[0];
                break;
            default:
                break;
        }

        if (null == domIsNull) {
            throw ('dom element should not be null');
        }

        // svg转canvas
        let nodesToRecover = [];
        let nodesToRemove = [];
        let svgElem;
        switch (domName.charAt(0)) {
            case '#':
                svgElem = document.getElementById(domName.substr(1)).getElementsByTagName('svg');
                break;
            case '.':
                svgElem = document.getElementsByClassName(domName.substr(1))[0].getElementsByTagName('svg');
                break;
            default:
                break;
        }

        let prepare = [];
        for (let i = 0; i < svgElem.length; i++) {
            prepare.push(0);
        }

        for (let i = 0; i < svgElem.length; i++) {
            let parentNode = svgElem[i].parentNode;
            let canvas = document.createElement('canvas');
            canvas.style.position = svgElem[i].style.position;
            canvas.width = parseInt(svgElem[i].style.width);
            canvas.height = parseInt(svgElem[i].style.height);
            canvas.style.left = '0';
            canvas.style.top = '0'; // 生成与svg对应尺寸的canvas
            let ctx = canvas.getContext('2d');
            let svg_xml = (new XMLSerializer()).serializeToString(svgElem[i]);
            let img = new Image();
            img.src = "data:image/svg+xml;base64," + window.btoa(svg_xml);
            img.onload = function () {
                ctx.drawImage(img, 0, 0);
                prepare[i] = 1;
                //download(canvas.toDataURL("image/png")); // 调试用
            }
            parentNode.appendChild(canvas); // 使用canvas代替svg进行截图
            nodesToRemove.push({ // 完成截图后删除canvas
                parent: parentNode,
                child: canvas
            });
            nodesToRecover.push({ // 完成截图后恢复svg
                parent: parentNode,
                child: svgElem[i]
            });
            parentNode.removeChild(svgElem[i]); // 暂时移除svg
        }

        return new Promise((resolve) => {
            let waitInterval = setInterval(() => {
                let isComplete = true; // 创建定时器,等待上面img.onload的异步操作
                for (let i = 0; i < prepare.length; i++) {
                    if (prepare[i] == 0) {
                        isComplete = false;
                        break;
                    }
                }
                if (isComplete) {
                    clearInterval(waitInterval);
                    // div转canvas截图
                    let domElem;
                    switch (domName.charAt(0)) {
                        case '#':
                            domElem = document.getElementById(domName.substr(1));
                            break;
                        case '.':
                            domElem = document.getElementsByClassName(domName.substr(1))[0];
                            break;
                        default:
                            break;
                    }

                    html2canvas(domElem, {
                        useCORS: true,
                        logging: true
                    }).then((cnv) => {
                        let imgUrl = cnv.toDataURL("image/png"); // 将canvas转换成img的src流,base64
                        for (let i = 0; i < nodesToRecover.length; i++) {
                            nodesToRecover[i].parent.appendChild(nodesToRecover[i].child);
                        }
                        for (let i = 0; i < nodesToRemove.length; i++) {
                            nodesToRemove[i].parent.removeChild(nodesToRemove[i].child);
                        }
                        resolve(imgUrl);
                    });
                }
            }, 20);
        });
    }

    /* 下载图片的方法 */
    function download(url) {
        let a = document.createElement('a');
        a.style.display = 'none';
        document.body.appendChild(a);
        let triggerDownload = $(a).attr("href", url).attr("download", "order" + generateRandomNumber() + ".png");
        triggerDownload[0].click();
        document.body.removeChild(a);
    }

    //生成随机数
    function generateRandomNumber() {
        return (new Date()).getTime();
        /*const randomNumber = Math.floor(Math.random() * 900000) + 100000;
        return randomNumber.toString();*/
    }

三、避坑指南

1.尺寸过大而无法成功生成图片

当使用html2canvas进行截图时,如果尺寸过大而无法成功生成图片,可以尝试以下解决方案:

  1. 减小截图区域尺寸:可以通过指定截图区域的宽度和高度来限制截图的范围。确定需要截图的具体区域,并设置合适的尺寸,以确保能够成功生成图片。

  2. 减少截图对象的复杂性:如果截图对象包含大量复杂的元素(如大量文字、图像、动画等),可以尝试简化截图对象,减少其中的元素数量或优化其结构,以减少截图的复杂度。

  3. 延迟截图操作:有时,页面中的某些元素可能需要一些时间才能完全加载和渲染完成。在截图之前,可以添加相应的延迟,以确保元素已经完全显示在页面上。可以使用setTimeout或者使用html2canvas提供的onclone回调函数来延迟截图操作。

  4. 分割截图:如果截图的尺寸仍然过大,可以尝试将截图区域分割为多个较小的部分进行截图,然后将这些部分拼接在一起以生成完整的图片。

  5. 使用其他截图工具:如果html2canvas无法满足你的需求,可以考虑使用其他可用的截图工具,比如Puppeteer、PhantomJS或者Selenium等。

2.返回的toDataURL()数据为 data:,的解决方法

当生成的canvas没有宽度和高度时,返回data:,,因此需要在div元素中设置对应的高度和宽度。

  • 设置为百分比,height: 100%;,无效;
  • 设置为绝对高度,如height: 1132px;

在这里插入图片描述

3.html2canvas截图空白问题

配置高宽选项即可。

 html2canvas(htmlDom, {
            useCORS: true,
            logging: true,
            /*  width: htmlDom.offsetWidth,
              height: htmlDom.offsetHeight,
              scrollX: 0,
              scrollY: 0,*/
            x: htmlDom.offsetWidth / 2,
            y: 0,
        }).then((canvas) => {}

在这里插入图片描述


@漏刻有时

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漏刻有时

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值