react单个页面截图和多个页面截图

article/2025/7/21 10:19:48

之前有一个需求是点击导出按钮,然后去各个页面截图,将图片传给后端,后端返回文件流,导出ppt报告。这个需求听到的时候头都大了,不知道怎么做,之后有思路了,在实现过程中也出现了各种问题,最后还是做完了(  撒花!)

一、首先来说一下单个页面截图

单个页面截图是比较简单的,通过插件domtoimage可以实现。

1.安装插件

yarn add dom-to-image

2.在需要截图的页面jsx里面引入该插件

import domtoimage from "dom-to-image";

3.截图

async function check() {let dom_policy = document.getElementById("policy");let formData_total = new FormData();if (dom_policy) {//  执行dom加载完成后的操作,例如echart的初始化操作await domtoimage.toPng(dom_policy).then((dataUrl) => {let formData = new FormData();let img = base64ToBlob(dataUrl, "命名.png");formData.append("port_presentation", img);if (formData.has("port_presentation")) {formData_total.append("area_review",formData.getAll('port_presentation'));}});
}
}

这里对代码进行一些解释:

(1)因为在该页面我需要截图两张,所以我在截图前创建一个fromData来存储两张截图

 let formData_total = new FormData();

formData_total相当于就是一个对象。

(2)每次截图完我需要一个对象来保存我的图片,因此在每个截图操作里面,我又创建了一个formData来存储

let formData = new FormData();

(3)因为new FromData()出来的相当于是一个对象,因此需要属性和属性值。

formData.append("port_presentation", img);

(4)将formData里面的值展开

 formData.getAll('port_presentation')

(5)base64ToBlob是将截图的数据进行转化

  let img = base64ToBlob(dataUrl, "命名.png");

(6)补充一下,formData.has可以检测当前属性是否有值

 formData.has('port_presentation')

截图完了,就可以发送请求给后端了

这里我采用的是fetch发送请求

  fetch(window.location.origin + `请求路径`, {responseType: "blob",method: "post",body: formData_total,}).then((res) => {const filename = res.headers.get("content-disposition").split(";")[1].split("=")[1];res.blob().then((blob) => {const link = document.createElement("a");link.style.display = "none";// a 标签的 download 属性就是下载下来的文件名link.download = filename;link.href = URL.createObjectURL(blob);document.body.appendChild(link);link.click();// 释放的 URL 对象以及移除 a 标签URL.revokeObjectURL(link.href);document.body.removeChild(link);});}).catch((res)=>{alert('导出失败')})

二、接下来说说多个页面截图

多个页面截图就是这个页面截图完了,自动跳到下个页面截图,一直到所有需要截图的页面截完为止,再发送请求。

我的框架是react,因此我用的状态机将各个页面联系起来。去改变状态机的值,让截图页面接受截图信号,进行自动跳转截图。

1.状态机,初始值设置为"导出ppt"

 

2. 点击导出按钮时,通过navigate进行路由跳转,并改变保存在状态机的值

  dispacth(pptActions("下一个页面的命名(比如:你好react)"));setTimeout(() => {navigate("下一个页面的路由");}, 3000);

3.自动跳转到下一个页面时,需要去获取刚刚保存到状态机的值,是否为"你好react",进行截图信号判断,执行截图函数check()。

//截图信号const ppt_key = useSelector((state) => {return state.ppt;});useEffect(() => {if (ppt_key == "你好react") {setTimeout(()=>{check();},3000)}}, [ppt_key]);

4.截图函数跟单页面差不多,但是由于会涉及到几十张截图,数量较大,因此我单独写了一个js文件来进行汇总截图文件。

  async function check() {let dom_policy = document.getElementById("policy");let dom_map = document.getElementById("map");// console.log(dom_policy);let formData_total = new FormData();if (dom_policy && dom_map) {//  执行dom加载完成后的操作,例如echart的初始化操作await domtoimage.toPng(dom_policy).then((dataUrl) => {let formData = new FormData();let img = base64ToBlob(dataUrl, "命名.png");formData.append("port_presentation", img);if (formData.has("port_presentation")) {formData_total.append("area_review",formData.getAll('port_presentation'));summaryFormData(formData.getAll('port_presentation'),'',"命名.png");}});if(formData_total.has('area_review')){dispacth(pptActions('下一个页面的命名'));setTimeout(()=>{navigate('下一个页面的路径');},5000)}
}
}

汇总js文件

let formData_ppt = new FormData();export const summaryFormData = (value, title, name, result) => {if (name == "命名.png" ||name == "命名.png" ||name == "命名.png") {formData_ppt = new FormData();}//为了分段发送请求,一次性发送大量数据会有问题,部分数据拿不到,因此这里就分成了3段let blob = new Blob(value);let file = new File([blob], name, { type: "image/png" });//这里根据后端需要需要加type类型
//这里根据后端需要的参数名,进行属性和属性值的添加  
if (title == "") {formData_ppt.append("area_review", file);} else if (title == "") {formData_ppt.append("edition_set", file);} else if (title == "") {formData_ppt.append("trend_predict", file);} else if (title == "") {formData_ppt.append("zero_carbon", file);}if (result == "完") {formDataFounction(formData_ppt, 0);}
};function formDataFounction(value, num) {if (num == 0) {fetch(window.location.origin + `请求路径`, {method: "post",body: value,}).then((response) => response.json()).then((data) => {console.log(data)}).catch((res) => {alert("导出失败");});} else {fetch(window.location.origin + `请求路径`, {responseType: "blob",method: "post",body: value,}).then((res) => {localStorage.removeItem("edition_list");localStorage.removeItem("scene_list");localStorage.removeItem("number");const filename = res.headers.get("content-disposition").split(";")[1].split("=")[1];res.blob().then((blob) => {const link = document.createElement("a");link.style.display = "none";// a 标签的 download 属性就是下载下来的文件名link.download = filename;link.href = URL.createObjectURL(blob);document.body.appendChild(link);link.click();// 释放的 URL 对象以及移除 a 标签URL.revokeObjectURL(link.href);document.body.removeChild(link);document.body.removeChild(exportPpt);});}).catch((res)=>{document.body.removeChild(exportPpt);alert('导出失败')})}
}

之后的每个页面都重复3、4,当一个阶段截图完成时,就发送一个信号让汇总js文件知道,可以发送请求了。我这里用的是多传一个参数"完"。

这里需要注意的是,用fetch发送请求,想要拿到返回的data数据,需要先执行

.then((response) => response.json())

才可以拿到。

具体参照上面的代码吧。

可能没说清楚,主要是太多了,有问题评论区讨论哦。


http://chatgpt.dhexx.cn/article/Eg0wx8BT.shtml

相关文章

JS页面截图

1、引入 js 【密码&#xff1a;gf33】 点击下载 html2canvas.min.js <script src"{url:static/octzz/js/html2canvas.min.js}"></script>2、html代码 <body><div><button type"button" class"layui-btn" onclick&q…

使用html2canvas.js实现页面截图

由于最近项目需求&#xff0c;需要实现html页面截图&#xff0c;经过查资料&#xff0c;找到了这个东东html2canvas&#xff0c;刚开始截出来的图片&#xff0c;空白、模糊、图片不完整&#xff0c;各种问题&#xff0c;但幸好有各路大神的见解&#xff0c;把问题解决了&#x…

vue页面截图;H5页面截图;vue项目中将特定网页内容生成图片(截图);html2canvas截图

功能&#xff1a; 1.兼容 PC 和 Mobile&#xff1b; 2.对指定的区域进行截取&#xff1b; 3.可以控制截图大小&#xff1b; 4.截图生成base64图片地址 一、安装插件 npm install html2canvas --save 或 yarn add html2canvas二、在.vue页面引入使用 import html2canvas fro…

Java实现HTML页面截图功能

概述 业务开发中&#xff0c;经常会有HTML页面截图&#xff0c;或打印另存为PDF文件的需求。本文即是HTML页面截图需求的技术调研过程的成文。不想看长篇大论的同学&#xff0c;可以直接看Selenium部分&#xff0c;本人最后也是采取此方案。 html2canvas 直接上代码&#xf…

2种方式!带你快速实现前端截图

导语 | 本文将介绍在前端开发中页面截图的两种方式&#xff0c;包括对其实现原理和使用方式进行详细阐述&#xff0c;希望能为更多前端开发者提供一些经验和帮助。 一、 背景 页面截图功能在前端开发中&#xff0c;特别是营销场景相关的需求中, 是比较常见的。比如截屏分享&…

Element el-row el-col 布局组件详解

点此查看全部文字教程、视频教程、源代码 本文目录 1. 背景2. 分栏布局3. 分栏间隔4. 分栏偏移4. 对齐方式5. 响应式布局6. 小结 1. 背景 element的布局方式与bootstrap原理是一样的&#xff0c;将网页划分成若干行&#xff0c;然后每行等分为若干列&#xff0c;基于这样的方式…

Android基础篇 屏幕横竖屏切换(layout-land)下篇

默认情况下Activity进行屏幕旋转会自动进行onDestroy并重新onCreate 一、非默认情况下 在AndroidManifest.xml的Activity中配置 <activityandroid:name".ui.activity.XXXXXActivity"android:launchMode"singleTask"android:screenOrientation"por…

Android屏幕共享解决方案

屏幕共享是增强互动体验&#xff0c;提高沟通效率的重要功能。以下是一些实现Android屏幕共享的解决方案&#xff1a; 1、使用视频通话功能&#xff1a;在Android中&#xff0c;可以使用视频通话功能实现屏幕共享。通过视频通话&#xff0c;可以将自己的屏幕内容以视频的方式分…

让div居中的方式的几种方法

让div水平居中的方式的几种方法。 文章目录 一、margin二、绝对定位三、子元素绝对定位父元素相对定位四、flex布局总结 一、margin 第一种方式我们可以利用外边距属性来使div水平垂直居中 先来看一段有问题的代码 <!DOCTYPE html> <html lang"en"> &…

html网页图片和文字水平居中垂直居中显示

关注公众号&#xff1a;”奇叔码技术“ 回复&#xff1a;“java面试题大全”或者“java面试题” 即可免费领取资料 下面代码一致&#xff1a;示例 自己做的网站效果示例 div相对于页面水平居中显示&#xff1a; 核心代码&#xff1a;margin&#xff1a;0 auto&#xff1b;…

Android 双屏异显(Presentation) 开发,将第二个页面投屏到副屏上

1. 背景 最近开发的一个项目&#xff0c;有两个屏幕&#xff0c;需要将第二个页面投屏到副屏上&#xff0c; 这就需要用到Android的双屏异显(Presentation)技术了&#xff0c;研究了一下&#xff0c;这里做下笔记。 我们那个副屏是一块汽车的后视镜(流媒体后视镜)&#xff0c;…

父子div元素水平垂直居中的七种方法

效果样式图如下: 方法一:利用定位和transform的方法来进行居中 说明&#xff1a;首先利用定位中的子元素绝对定位和父元素相对定位的方法来,top:50% 和left:50%会使子元素在父元素中向下移动250px,向右移动250px,子元素因自身有高度和宽度,这会导致子元素不能完全居中的情况,t…

用户体验思考与flex三坑:元素不均分、溢出不省略和垂直不滚动

flex已经越来越成为前端不可避免的话题。曾经为了搞清flex的原理偶然画了一张图。但后来发现只是冰山一角。 在某些你想实现的交互效果中使用flex后可能会发现并不起作用。通过我的实践&#xff0c;大致有三个问题&#xff1a;子元素不平分父元素空间、对文字设置了溢出省略却…

DIV居中的经典方法

参考&#xff1a;https://www.cnblogs.com/rubykakas/articles/7992662.html 1. 实现DIV水平居中 设置DIV的宽高&#xff0c;使用margin设置边距0 auto&#xff0c;CSS自动算出左右边距&#xff0c;使得DIV居中。 div{width: 100px;height: 100px;margin: 0 auto; } 缺点&…

局域网屏幕共享_给安卓手机连一个大屏幕——多端协作(六)

好久不见,时下情势严峻,我们这儿封村了,生活变得更加不方便了。本来在网上买了肉,等到终于发货送到县城,我却不能进城去取了…… 希望顺丰营业点有冰箱,我的肉不会坏掉 今天给大家介绍的是Android系统的无线投屏功能,简单来说就是将支持的设备作为安卓手机的外接屏幕,以…

安卓手机与蓝牙模块联合调试(二)—— 单片机蓝牙控制LED灯亮灭(上)

系列博文&#xff1a; &#xff08;1&#xff09;安卓手机与蓝牙模块联合调试&#xff08;一&#xff09;——蓝牙模块的串口通讯 &#xff08;2&#xff09;安卓手机与蓝牙模块联合调试&#xff08;二&#xff09;—— 单片机蓝牙控制LED灯亮灭&#xff08;上&#xff09; …

android 多屏幕显示activity,副屏,无线投屏

目录 1. 首先&#xff0c;需要一个副屏 1. 1 可以通过代码的形式自己创建VirtualDispaly ,创建副屏。 1.2 或者&#xff0c;在手机的开发者模式中直接开启模拟副屏&#xff0c;也是可以的。 2.0 怎么利用这个副屏幕&#xff1f; 2.1 用作 presentation 演示ppt&#xff1…

【Android 屏幕扩展/共享】5分钟搞定—电脑 与 手机共享屏幕

回去看看老家是不是还有旧平板电脑&#xff0c;可以跨设备&#xff0c;共享屏幕哦 一些远程控制软件&#xff0c;诸如&#xff1a;TeamViewer、AnyDesk等。 但是这次我要介绍的是 一款远程显示软件&#xff0c;甚至可以理解成一款简易的KVM系统。 虽然市面上许多远程控制软件…

Android设备之间投屏功能实现

简介 简单实现两个android设备之间的投屏功能。设备间通信是通过局域网&#xff0c;需要连接同一个wifi。 录屏用到系统的MediaProjection&#xff0c;MediaProjectionManager&#xff0c;而编解码用的是MediaCodec&#xff0c;所以设备需要有DSP芯片&#xff0c;大部分手机应…

CSS实现垂直居中的5种方法

第一种 position定位margin负距离 前提是知道居中元素的宽高&#xff0c;首先给居中元素定位&#xff0c;之后设置margin的负距离为具体宽高的一半便可达到垂直居中效果 <style>.box1 {height: 300px;width: 300px;border: 10px solid pink;position: relative;}.box2 {…