首页 > 其他分享 >vue pc使用htmlCanvas Jspdf 实现点击将页面生成图片并转成pdf下载

vue pc使用htmlCanvas Jspdf 实现点击将页面生成图片并转成pdf下载

时间:2023-04-12 15:36:29浏览次数:38  
标签:Jspdf vue const pageHeight lableListID pc var pdf document

<template>
  <div id="main" ref="workbench" v-loading="loading" class="echartsPdf">
    需要的内容
  </div>
</template>

<script>
import html2canvas from 'html2canvas'
import Jspdf from 'jspdf'
export default {
  name: 'ReportDetail',
  directives: {},
  data() {
    return {
    }
  },
  watch: {
  },
  mounted() {
  },
  created() {
    this.$nextTick(async() => {
      await this.initAxis()
    })
  },
  beforeDestroy() {
    // cleartimeout(this.timer)
  },
  methods: {
    // 避免分页被截断
    outPutPdfFn() {
      const vm = this
      const A4_WIDTH = 592.28
      const A4_HEIGHT = 841.89
      // $myLoading 自定义等待动画组件,实现导出事件的异步等待交互
      vm.$nextTick(() => {
        // dom的id。
        const target = document.getElementById('main')
        const pageHeight = target.scrollWidth / A4_WIDTH * A4_HEIGHT
        // 获取分割dom,此处为class类名为item的dom
        const lableListID = document.getElementsByClassName('echartsSection')
        // 进行分割操作,当dom内容已超出a4的高度,则将该dom前插入一个空dom,把他挤下去,分割
        for (let i = 0; i < lableListID.length; i++) {
          const multiple = Math.ceil((lableListID[i].offsetTop + lableListID[i].offsetHeight) / pageHeight)
          if (this.isSplit1(lableListID, i, multiple * pageHeight)) {
            const divParent = lableListID[i].parentNode // 获取该div的父节点
            const newNode = document.createElement('div')
            newNode.className = 'emptyDiv'
            newNode.style.background = '#01195e'
            const _H = multiple * pageHeight - (lableListID[i].offsetTop + lableListID[i].offsetHeight)
            newNode.style.height = _H + 30 + 'px'
            newNode.style.width = '100%'
            const next = lableListID[i].nextSibling // 获取div的下一个兄弟节点
            // 判断兄弟节点是否存在
            console.log(next)
            if (next) {
              // 存在则将新节点插入到div的下一个兄弟节点之前,即div之后
              divParent.insertBefore(newNode, next)
            } else {
              // 不存在则直接添加到最后,appendChild默认添加到divParent的最后
              divParent.appendChild(newNode)
            }
          }
        }
      // 页面转换下载 this.pdf1() }) }, // 判断是否需要添加空白div isSplit1(nodes, index, pageHeight) { // 计算当前这块dom是否跨越了a4大小,以此分割 if (nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight) { return true } return false }, pdf1() { // 避免出现浏览器滚动条导致的内容不全处理 document.body.scrollTop = 0 // div内部滚动导致内容不全处理 const that = this document.getElementById('app').style.height = 'auto' setTimeout(() => { html2canvas(document.getElementById('main'), { background: '#01195e', allowTaint: true // height: document.getElementById('upload').scrollHeight, // windowHeight: document.getElementById('upload').scrollHeight }).then(canvas => { var contentWidth = canvas.width var contentHeight = canvas.height // 一页pdf显示html页面生成的canvas高度; var pageHeight = contentWidth / 592.28 * 841.89 // 未生成pdf的html页面高度 var leftHeight = contentHeight // 页面偏移 var position = 0 // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 var imgWidth = 595.28 var imgHeight = 592.28 / contentWidth * contentHeight var pageData = canvas.toDataURL('image/jpeg', 1.0) var pdf = new Jspdf('', 'pt', 'a4') // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89) // 当内容未超过pdf一页显示的范围,无需分页 if (leftHeight < pageHeight) { 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(`${that.rowInfo.reportName}.pdf`) }) }, 300) }, handleChange() {}, async initAxis() { this.loading = true const that = this this.timer = setTimeout(() => { that.outPutPdfFn() }, 8 * 1000) } } } </script> <style scoped></style>

 

标签:Jspdf,vue,const,pageHeight,lableListID,pc,var,pdf,document
From: https://www.cnblogs.com/suka/p/17309872.html

相关文章

  • 在.NET Core使用 HttpClient 的正确方式
    前言HttpClient是.NETFramework、.NETCore或.NET5以上版本中的一个类,用于向WebAPI发送HTTP请求并接收响应。它提供了一些简单易用的方法,如GET、POST、PUT和DELETE,可以很容易地构造和发送HTTP请求,并处理响应数据。它是我们比较常用的官方HTTP请求组件,那么你们都......
  • 基于vue3+ts+vite的项目使用‘unplugin-auto-import/vite’插件,自动全局导入api的注意
    ​ 1.首先安装插件npminstallunplugin-auto-import@vitejs/plugin-vue-D2.安装完成后在vite.congfig.ts中配置,红色部分就是关于插件的基础自动导入部分,这样就可以将vue和router的相关api全局导入了,importAutoImportfrom"unplugin-auto-import/vite"exportdefaultde......
  • 解决vue-elment-admin mock转在线接口地址跨域问题
    devServer:{  port:port,  open:true,  overlay:{   warnings:false,   errors:true  },  //before:require('./mock/mock-server.js')  proxy:{//[process.env.VUE_APP_BASE_API]  vue中env.文件中配置的api名称......
  • vuex store
    一,vuex:状态管理(集中式存储应用的所有组件的状态)vuex是vue的插件store:商店二,vuex有那些属性staste:{}-------------用来放数据的,类似于组件中的datagetters:{}-------------就是一个计算属性[类似于组件中的computed]mutations:{}-----------就是一个存放方法的[类似......
  • 新员工入职,前端基础环境变量的配置!node、nvm、vue-cli的安装和下载
    1.安装nvm及配置首先下载nvm不要下载node,如果电脑已经有node的话需要卸载node,并使用命令提示符来查看node的位置(wherenode)手动删除nvm下载链接:https://nvm.uihtm.com/下载最新版本,next傻瓜式操作(需要注意的是)选择node.js文件位置,如果需要更改,请在这里进行更改......
  • 【基础知识】PCB布局设计入门步骤
    准备是成功的基石,在PCB设计中也是如此。改进和增长将伴随经验,首先做好准备能够充分利用经验获得成功。为了帮助你做好准备,下面分享一些基本的PCB布局设计步骤。从良好的原材料入手是您PCB布局设计的第一步无论打算执行什么任务,要想成功,就需要从优质的材料入手。就像高级木匠不会用......
  • vue项目中发布新版本线上自动清缓存
    背景最近项目更新频繁,每次一更新客户都说还跟之前的一样。一查原因是因为客户没有清空浏览器的缓存。所以为了方便客户看到最新版本,开始调研再发布新版本后自动清理缓存。方案每次打包后的js和css都加上hash值后缀。当文件发生改变时,hash值也改变。这样就不会走缓存举个例子v......
  • 用Abp实现两步验证(Two-Factor Authentication,2FA)登录(二):Vue网页端开发
    @目录发送验证码登录退出登录界面控件获取用户信息功能项目地址前端代码的框架采用vue.js+elementUI这套较为简单的方式实现,以及typescript语法更方便阅读。首先添加全局对象:loginForm:登录表单对象twoFactorData:两步验证数据,showTwoFactorSuccess:是否显示两步验证成......
  • Vue3+element-plus封装文字超出一行,省略号显示,鼠标悬浮展示全部
    1.组件封装<template><el-tooltipeffect="dark":disabled="isShowTooltip":content="content"placement="top"><p:class="['line1',className]"@mouseover="onMouseOver(refNa......
  • Vue.js 路由的props配置
    视频index.js(解构赋值,连续解构赋值)Message.vue7.路由的props配置​ 作用:让路由组件更方便的收到参数{ name:'xiangqing', path:'detail/:id', component:Detail, //第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件 //pr......