html2canvas截图

需求:实现一个快照功能。
快照:要根据需求实现页面长截图(整个页面)或者页面中的某部分进行截图

技术:canvas是底层,其中我们使用了基于canvas的第三方插件

核心原理:html2canvas.js 能够实现在用户浏览器端直接对整个或部分页面进行截屏(包括页面中写的样式)

问题:页面布局是flex布局,页面上下固定,中间自适应的时候,当我们通过document.body获取截到的就只是可视区域的内容,当页面内容有超出时,因为最外层盒子不能滑动,所以会导致截取到的图片不全。但如果单独对中间自适应的内容截取,中间自适应超出的内容也能截取到,这是因为html2canvas在截取时会对设置的样式也生效。也就是说界面是什么样的css,截图得到的就是一样的(相同的输入得到相同的输出)

解决思路:全截屏写两套独立的元素并布局,当截图的是时候显示全截图的元素(可全局滑动),未截图时展示局部滑动的元素。

当全截图时,需要隐藏页面部分不需要截图的元素,
给元素添加 data-html2canvas-ignore=“true”

<div data-html2canvas-ignore class="group_4 flex-col">
</div>

用法: 安装html2canvas

npm install html2canvas  //安装
import html2canvas from 'html2canvas'; 使用




const uploadSign = async () => {
  data.form.confirmStatus = "MANUAL_SIGN";
  Toast("加载中");
  const billImageRes = await uploadFile(document.body);
  console.log(billImageRes);
  const signRes = await uploadFile(document.querySelector("#sign-img"));
  console.log(signRes, "signRes图片地址===");
  const params = {
    id: data.form.id,
    billImage: billImageRes.data.file.pic_id,
    signatureImage: signRes.data.file.pic_id,
    detailUrl: data.form.detailUrl,
  };
  // console.log(params);
  // return;
  const res: any = await addFscSignature(params);
  if (res.code != "000000") {
    data.form.signPictureUrl = "";
    data.form.confirmStatus = "UN_SIGN";
    vuexStore.commit("setIsUpdate", false);
    isScreenShot.value = false;
    Toast.fail(res.msg);
  } else {
    data.form.confirmStatus = "MANUAL_SIGN";
    isScreenShot.value = false;
    await loadData();

    if (router.currentRoute.value.query.pageSource == "H5") {
      vuexStore.commit("setIsUpdate", true);
    }
  }
};

问题:
图片跨域:如果需要截图的地方包含其他域名的图片,那么会出现跨域问题

解决:

1)设置useCORS:true,
2**把后端的图片转成base64**

```javascript
1:通过调取接口转换
1.1 得到接口结果在页面渲染需赋值:**data:image/png;base64**

```javascript
const res = await convertToBase64({
            img: response.data.imageUrl,
            // img: 'https://dsl-ds.dslbuy.com/A37164C4830F49D7ACC824B97B346BB7.png', //response.data.imageUrl,
          });
    console.log(res.data, "原生返回的图片地址===", res);
data.form.signPictureUrl = `data:image/png;base64,${res.data}`;

2:前端转换
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
// e.target.result 即为base64结果
console.log(e.target.result);
};


3)将图片都放在同一个域名下


注意:
1:document获取需要截取的HTML元素,其中注意,通过选择器获取的元素不能重名,需唯一(如#sign-img只能出现一次)
2:当页面中有图片时,需要设置   useCORS: true, //配置允许跨域
uploadFile :得到的二进制图片提交给接口
```javascript
const uploadFile = async (dom) => {
  const options = {
    backgroundColor: null,
    useCORS: true, //配置允许跨域
    dpi: 300, // 处理模糊问题
    height: dom.scrollHeight + dom.scrollTop + 40,
  };
  document.documentElement.scrollTop = 0;
  document.body.scrollTop = 0;

  const canvas = await html2canvas(dom, options);
  const file = canvas.toDataURL("image/png");
  console.log(file, "截到的图片=====", canvas);
  var formData = new FormData();
  let blob = dataURLtoFile(file, "image/jpeg");
  let fileOfBlob = new File([blob], new Date() + ".jpg");
  formData.append("file", fileOfBlob);

  const res = await addFile(formData);
  return res;
};

3:同时页面中的图片元素设置**crossorigin=“anonymous”**允许跨域

<img
    :src="data.form.signPictureUrl"
       alt="sign"
       class="sign-img"
       crossorigin="anonymous"
  />

4:当全截图的时候,需要分别设置如下两点 scrollTop=0

  document.documentElement.scrollTop = 0;
  document.body.scrollTop = 0;

5:截图得到的是base64的图片,但是我们传递给后端的一般是二进制,所以需要进行base64和二进制之间的转换
dataURLtoFile :文件转换

const dataURLtoFile = (dataURI, type) => {
  let binary = atob(dataURI.split(",")[1]);
  let array = [];
  for (let i = 0; i < binary.length; i++) {
    array.push(binary.charCodeAt(i));
  }
  return new Blob([new Uint8Array(array)], { type: type });
};

扩展:不同文件之间的转换
https://editor.csdn.net/md/?articleId=134682076







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值