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

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

  • 一、构建HTML容器
  • 二、html2canvas截图封装函数
  • 避坑指南
    • 1.尺寸过大而无法成功生成图片

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转canvaslet 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对应尺寸的canvaslet 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({ // 完成截图后删除canvasparent: parentNode,child: canvas});nodesToRecover.push({ // 完成截图后恢复svgparent: 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流,base64for (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等。


@漏刻有时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/31438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go学习第八天

签名 func (a *Account) Sign(message []byte) ([]byte, error) {hash : crypto.Keccak256Hash(message)signature, err : crypto.Sign(hash.Bytes(), a.privateKeyECDSA)if err ! nil {log.Fatal(err)}signMsg : []byte(hexutil.Encode(signature))return signMsg, err }验签…

CentOS7 安装远程桌面

换源 设置镜像源为清华源&#xff1a; sudo sed -e s|^mirrorlist|#mirrorlist|g \-e s|^#baseurlhttp://mirror.centos.org/centos|baseurlhttps://mirrors.tuna.tsinghua.edu.cn/centos|g \-i.bak \/etc/yum.repos.d/CentOS-*.repo详见 https://mirrors.tuna.tsinghua.edu.…

函数与方法有区别?

有区别&#xff0c;当然是有区别。 不管是java、rust还是go&#xff0c;他们都是不一样的。 先看定义&#xff1a; 函数&#xff08;Function&#xff09; 是一段独立的代码块&#xff0c;用于执行特定的任务。函数可以被多次调用&#xff0c;并且可以接受参数和返回结果。在G…

尼科彻斯定理

目录 1.题目概述 2.题解 思路分析 具体实现 1.题目概述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 例如&#xff1a; 1^31 2^335 3^37911 4^313151719 输入一个正整数m&#xff08;m≤100&#xff09;&#xff0c;将…

pytorch 训练过程内存泄露/显存泄露debug记录:dataloader和dataset导致的泄露

背景 微调 mask-rcnn 代码&#xff0c;用的是 torchvision.models.detection.maskrcnn_resnet50_fpn 代码&#xff0c;根据该代码的注释&#xff0c;输入应该是&#xff1a; images, targetsNone (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Te…

【大数据】-- 部署 Flink kubernetes operator

目录 1.说明 1.1 版本 1.2 kubernetes 环境 1.3 参考 2.安装步骤 2.1 安装本地 kubernetes 环境

Oracle 使用 CONNECT_BY_ROOT 解锁层次结构洞察:在 SQL 中导航数据关系

CONNECT_BY_ROOT 是一个在 Oracle 数据库中使用的特殊函数&#xff0c;它通常用于在层次查询中获取根节点的值。在使用 CONNECT BY 子句进行层次查询时&#xff0c;通过 CONNECT_BY_ROOT 函数&#xff0c;你可以在每一行中获取根节点的值&#xff0c;而不仅仅是当前行的值。 假…

Vue3 实现产品图片放大器

Vue3 实现类似淘宝、京东产品详情图片放大器功能 环境&#xff1a;vue3tsvite 1.创建picShow.vue组件 <script lang"ts" setup> import {ref, computed} from vue import {useMouseInElement} from vueuse/core/*获取父组件的传值*/ defineProps<{images:…

从支付或退款之回调处理的设计,看一看抽象类的使用场景

一、背景 抽象类&#xff0c;包含抽象方法和实例方法&#xff0c;抽象方法待继承类去实例化&#xff0c;正是利用该特性&#xff0c;以满足不同支付渠道的差异化需求。 我们在做多渠道支付的时候&#xff0c;接收支付或退款的回调报文&#xff0c;然后去处理。这就意味着&…

【python 深度学习】解决遇到的问题

目录 一、RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb 二、AttributeError: module ‘tensorflow’ has no attribute ‘flags’ 三、conda 更新 Please update conda by running 四、to search for alternate channels that…

Tomcat部署SpringBoot项目

1.修改打包方式 pom.xml 里 加上 <packaging>war</packaging>2.移除内嵌的Tomcat <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope…

Java-jar和war包的区别

jar包和war包的区别&#xff1a; 1、war是一个web模块&#xff0c;其中需要包括WEB-INF&#xff0c;是可以直接运行的WEB模块&#xff1b;jar一般只是包括一些class文件&#xff0c;在声明了Main_class之后是可以用java命令运行的。 2、war包是做好一个web应用后&#xff0c;通…

Kubernetes 调度 约束

调度约束 Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面建立 Pod 和 Container。 APIServer…

腾讯云轻量应用服务器和云服务器有什么区别?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

饿了么输入框限制只能输入数字,并且保留小数

可以使用饿了么ui中的input-number组件实现输入框只能输入数字&#xff0c;这样就不能输入数字以外的&#xff0c;controls隐藏输入框左右俩边的加减按钮&#xff0c;precision小数点保留多少位&#xff0c;2则是俩位&#xff0c;但是会导致默认值为0.00的情况&#xff0c;俩种…

开源数据库Mysql_DBA运维实战 (DDL语句)

DDL DDL语句 数据库定义语言&#xff1a;数据库、表、视图、索引、存储过程. 例如:CREATE DROP ALTER DDL库 定义库{ 创建业务数据库&#xff1a;CREAATE DATABASE ___数据库名___ ; 数据库名要求{ a.区分大小写 b.唯一性 c.不能使用关键字如 create select d.不能单独使用…

图像识别模型与训练策略

图像预处理 1.需要将图像Resize到相同大小输入到卷积网络中 2.翻转、裁剪、色彩偏移等操作 3.转化为Tensor数据格式 4.对RGB三种颜色通道进行标准化 data_transforms {train: transforms.Compose([transforms.Resize([96, 96]),transforms.RandomRotation(45),#随机旋转&…

unable to write symref for HEAD: Permission denied

今天从gitee上面克隆项目到本地时报错如下 warning: unable to unlink ‘D:/IDEAcode/ruiji1.0/.git/HEAD.lock’: Invalid argument error: unable to write symref for HEAD: Permission denied 解决方法&#xff1a;将要存放项目的文件夹权限修改为完全控制 原先权限&…

GO学习之 接口(Interface)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 文章目录 GO系列前言一、什么是…

什么是MVCC

问题描述 对于 MVCC 的理解&#xff0c;我觉得可以先从数据库的三种并发场景说起&#xff1a; 第一种&#xff1a;读读 线程 A 与线程 B 同时在进行读操作&#xff0c;这种情况下不会出现任何并发问题。 第二种&#xff1a;读写 线程 A 与线程 B 在同一时刻分别进行读和写…