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

之前有一个需求是点击导出按钮,然后去各个页面截图,将图片传给后端,后端返回文件流,导出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())

才可以拿到。

具体参照上面的代码吧。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值