当前位置: 首页 > news >正文

将图表和表格导出为PDF的功能

<template>
  <div>
    <div
      ref="pdfContent"
      style="position: relative; width: 800px; margin: 0 auto"
    >
      <!-- ECharts 图表 -->
      <div id="chart" style="width: 100%; height: 400px" />

      <!-- Element UI 表格 -->
      <el-table
        ref="myTable"
        :data="tableData"
        style="width: 100%; margin-top: 20px"
        border
        stripe
      >
        <el-table-column prop="date" label="日期" width="180" />
        <el-table-column prop="name" label="姓名" width="180" />
        <el-table-column prop="address" label="地址" />
      </el-table>
    </div>
    <button @click="exportPDF">导出PDF</button>
  </div>
</template>

<script>
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
import * as echarts from 'echarts'
import 'element-ui/lib/theme-chalk/index.css' // 确保引入了Element UI的样式

export default {
  data() {
    return {
      tableData: [
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }
      ],

      tableDataeer: [
        {
          date: '2016-05-02',
          name: [
            { add: '数据', cs: '23' },
            { add: '数据1', cs: '23' }
          ],
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-02',
          name: [
            { add: '数据1', cs: '231' },
            { add: '数据11', cs: '231' }
          ],
          address: '上海市普陀区金沙江路 1518 弄'
        }
      ]
    }
  },
  mounted() {
    this.initChart()
  },
  methods: {
    initChart() {
      const chartDom = document.getElementById('chart')
      const myChart = echarts.init(chartDom)
      const option = {
        title: {
          text: 'Referer of a Website',
          subtext: 'Fake Data',
          left: 'center'
        },
        tooltip: {
          trigger: 'item'
        },
        legend: {
          orient: 'vertical',
          left: 'right',
          overflow: 'truncate', // 超出部分截断
          ellipsis: '...' // 显示省略号
        },
        series: [
          {
            name: 'Access From',
            type: 'pie',
            radius: '50%',
            data: [
              { value: 1048, name: 'Search Engine' },
              { value: 735, name: 'Direct' },
              { value: 580, name: 'Email' },
              { value: 484, name: 'Union Ads' },
              { value: 300, name: 'Video Ads' }
            ],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
              }
            }
          }
        ]
      }
      myChart.setOption(option)
    },
    exportPDF() {
      const element = this.$refs.pdfContent
      html2canvas(element).then((canvas) => {
        const imgData = canvas.toDataURL('image/png')
        // eslint-disable-next-line new-cap
        const pdf = new jsPDF({
          orientation: 'portrait',
          unit: 'pt',
          format: 'a4'
        })

        const imgProps = pdf.getImageProperties(imgData)
        const margin = 20 // 设置页边距
        const pdfWidth = pdf.internal.pageSize.getWidth() - margin * 2 // 减去左右边距
        const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width // 按比例计算高度

        let position = margin // 初始Y位置(顶部边距)
        let remainingHeight = pdfHeight // 剩余需要渲染的高度

        while (remainingHeight > 0) {
          // 当前页可用的高度(减去上下边距)
          const pageHeight = pdf.internal.pageSize.getHeight() - margin

          // 计算本次渲染的高度(不能超过页面剩余高度)
          const renderHeight = Math.min(remainingHeight, pageHeight - position)

          // 添加图像部分
          pdf.addImage(
            imgData,
            'PNG',
            margin, // x位置(左边距)
            position - (remainingHeight - pdfHeight), // y位置(考虑偏移)
            pdfWidth,
            renderHeight,
            null,
            'FAST' // 使用FAST模式提高性能
          )

          remainingHeight -= renderHeight
          position += renderHeight

          // 如果还有内容未渲染,添加新页面
          if (remainingHeight > 0) {
            pdf.addPage()
            position = margin // 新页面从顶部边距开始
          }
        }

        pdf.save('chart_and_table.pdf')
      })
    }
  }
}
</script>

<style scoped>
/* 你的样式 */
</style>

主要需要处理的问题:

  1. 内容截断问题

    • 当内容超过一页时,分页逻辑可能会导致内容被截断在页面中间

    • 特别是表格行可能会被不自然地分割在两页之间

  2. 样式完整性问题

    • Element UI表格的样式可能在PDF中显示不完整

    • ECharts图表在高分辨率导出时可能模糊

  3. 性能优化

    • 对于大量数据,html2canvas渲染可能较慢

    • PDF生成过程可能阻塞UI

  4. 布局适应性

    • 固定宽度(800px)可能在不同设备上显示不一致

    • 边距控制需要更精细

http://www.dtcms.com/a/108879.html

相关文章:

  • ThreadLocalMap的作用和特点
  • cobbler自动最小化安装centos,并配置地址
  • springboot+easyexcel实现下载excels模板下拉选择
  • Spring Boot 的配置文件
  • 网络空间安全(50)JavaScript基础语法
  • C#:重构(refactoring)
  • 【Spring Cloud Alibaba】:Nacos 使用全详解
  • CExercise04_1位运算符_1 用位运算符判断某个整数是否为奇数
  • 购物车(V2装饰器)
  • 算法:优选(1)
  • RK3568驱动 SPI主/从 配置
  • 基于微信小程序的医院挂号预约系统设计与实现
  • Apache Doris 2025 Roadmap:构建 GenAI 时代实时高效统一的数据底座
  • WRF-Chem 中出现real.exe错误(psfc 计算问题)- MOZART
  • Apache BookKeeper Ledger 的底层存储机制解析
  • 配置单区域OSPF
  • ARM—LED,看门狗关闭,按钮,时钟,PWM定时器,蜂鸣器
  • 【前端扫盲】postman介绍及使用
  • 走向多模态AI之路(三):多模态 AI 的挑战与未来
  • 【家政平台开发(12)】家政平台数据库设计:从MySQL到MyBatis-Plus实战
  • 多个参考文献插入、如何同时插入多个参考文献:如[1,2]、[1-3]格式
  • 搬砖--贪心+排序的背包
  • 请谈谈分治算法,如何应用分治算法解决大规模问题?
  • Pico4 Pro VR 和HTC Vivi 哪个好些
  • ngx_getpid() ngx_parent = ngx_getppid()
  • [C语言笔记]09、指针
  • 代码随想录Day31
  • 作用域与上下文:JavaScript魔法森林探秘
  • Python每日一题(14)
  • J1 ResNet-50算法实战与解析