vue3 实现截图当前dom节点为图片与下载为pdf文件

28 篇文章 4 订阅

vue3 实现截图当前dom节点为图片与下载为pdf文件

utils / index.ts

  • 安装依赖 js pnpm i html2canvas -D pnpm i jspdf -D
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

import type { HTMLElement } from "vue"

// 生成图片 name文件名称 dom节点
export function downPicture(dom:HTMLElement,name:string) {
    const shareContent = dom; // 需要截图的包裹的(原生的)DOM 对象
    const width = shareContent.offsetWidth ; // 获取dom 宽度
    const height = shareContent.offsetHeight ; // 获取dom 高度
    const canvas = document.createElement('canvas'); // 创建一个canvas节点
    canvas.width = width * 1.4; // 定义canvas 宽度 * 缩放
    canvas.height = height * 1.4; // 定义canvas高度 *缩放
    let a = document.createElement('a');
    let opts = {
        canvas,
        scale: 1.4,
        logging: false, // 日志开关,便于查看html2canvas的内部执行流程
        useCORS: true // 【重要】开启跨域配置
    };
    return new Promise((res, rej)=>{
        html2canvas(shareContent, opts).then((canvas) => {
            let dom = document.body.appendChild(canvas);
            dom.style.display = 'none';
            a.style.display = 'none';
            document.body.removeChild(dom);
            let blob:Blob = dataURLToBlob(dom.toDataURL('image/png'));
            a.setAttribute('href', URL.createObjectURL(blob));
            a.setAttribute('download', name + '.png');
            document.body.appendChild(a);
            a.click();
            URL.revokeObjectURL(blob);
            document.body.removeChild(a);
            res();
        });
    });
}
// ie 图片转格式
function dataURLToBlob(dataurl:string) { 
    var arr = dataurl.split(','); 
	var mime = arr[0].match(/:(.*?);/)[1];
    var bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type: mime});
}
// 有后台服务的
export function downloadPdf(excelUrl:string, reportName:string, callback:Function) {
    fetch(excelUrl, {
        headers: {
        }
    }).then(res => {
        console.log(res.status);
        if (res.status == 200) {
            return res.blob().then(blob => {
                var filename = `${reportName}.pdf`;
                if (window.navigator.msSaveOrOpenBlob) {
                    navigator.msSaveBlob(blob, filename); // 兼容ie10
                } else {
                    var a = document.createElement('a');
                    document.body.appendChild(a); // 兼容火狐,将a标签添加到body当中
                    var url = window.URL.createObjectURL(blob); // 获取 blob 本地文件连接 (blob 为纯二进制对象,不能够直接保存到磁盘上)
                    a.href = url;
                    a.download = filename;
                    a.target = '_blank'; // a标签增加target属性
                    a.click();
                    a.remove(); // 移除a标签
                    window.URL.revokeObjectURL(url);
                    callback && callback();
                }
            });
        } else {
            return Promise.reject('服务器错误');
        }
    }).catch((e)=>{
        callback && callback(e);
    });
};
// 下载pdf
function exportDataPdf(el: HTMLElement, fileName: string) { 
	html2canvas(el, {
	  scale: 3, // 设置缩放
	  useCORS: true, // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
	  allowTaint: true,
	  logging: false, // 打印日志用的 可以不加默认为false
	  backgroundColor: '#ffffff'
	}).then((canvas) => {
	  const contentWidth = canvas.width;
	  const contentHeight = canvas.height;
	  // 一页pdf显示html页面生成的canvas高度;
	  const pageHeight = (contentWidth / 592.28) * 841.89;
	  // 未生成pdf的html页面高度
	  let leftHeight = contentHeight;
	  // 页面偏移
	  let position = 0;
	  // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
	  const imgWidth = 595.28;
	  const imgHeight = (595.28 / contentWidth) * contentHeight;
	  const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
	// const ctx = canvas.getContext('2d');
	  // 添加水印
	  // ctx.textAlign = 'center';
	  // ctx.textBaseline = 'middle';
	  // ctx.rotate((25 * Math.PI) / 180);
	  ctx.font = '20px Microsoft Yahei';
	  // ctx.fillStyle = 'rgba(184, 184, 184, 0.8)';
	  // for (let i = contentWidth * -1; i < contentWidth; i += 240) {
	  //   for (let j = contentHeight * -1; j < contentHeight; j += 100) {
	  //     // 填充文字,x 间距, y 间距
	  //     ctx.fillText('水印名', i, j);
	  //   }
	  // }
	  const pageData = canvas.toDataURL('image/jpeg', 1.0);
	  const pdf = new jsPDF("p", "pt", "a4");
	  if (leftHeight < pageHeight) {
		// 在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
		pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
	  } else {
	  // 分页
	  while (leftHeight > 0) {
		  pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
		  leftHeight -= pageHeight;
		  position -= 841.89;
		  // 避免添加空白页
		  if (leftHeight > 0) {
			 pdf.addPage();
		  }
	  }
	  }
	  // 可动态生成
	  pdf.save(`${fileName}.pdf`);
	})
}

let $utils = {
    downPicture,
    downloadPdf,
	exportDataPdf
};

function getUtils() {
    return $utils;
}
export { getUtils };

main.ts

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

import { getUtils } from "./utils/index"

const app = createApp(App)

console.log('getUtils',getUtils);
app.config.globalProperties.$utils = getUtils()

app.use(router)
app.use(store)
app.mount('#app')

about.vue

<template>
  <div ref="myDom" class="my-dom">
	AboutIndex
	我是{{ name1 }}
	我是测试图片的
	<img src="./img/test.png" alt="">
	<van-button type="primary" @click="picDownload">下载图片</van-button>
	<van-button type="primary" @click="pdfDownload">下载pdf</van-button>
  </div>
</template>

<script setup lang="ts" name='AboutIndex'>
import { getCurrentInstance,ref } from "vue"
// import axios from "axios"
// import http from "@/utils/request"
const name1 = ref<String>('ppp')

const { proxy } = getCurrentInstance()
console.log('proxy',proxy, proxy.$utils);
const myDom = ref(null)
const picDownload = async () => {
    // 生成长图
    await proxy.$utils.downPicture( myDom.value,'pic图片啊');
}
const pdfDownload = async () => {
    // 生成pdf
    await proxy.$utils.exportDataPdf( myDom.value,'pdf文件啊');
}

</script>
<style scoped>
.my-dom {
	padding: 20px;
}
</style>
```
## 效果

![在这里插入图片描述](https://img-blog.csdnimg.cn/b9f045aa148945b38df339d41b56aee1.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/81c2a618cb28481b90bef8f65cf00eba.png)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值