前端js实现网页高清导出pdf及ppt

725 阅读1分钟
import pptxgen from 'pptxgenjs'
import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'
import dayjs from 'dayjs'

const loadingHide = () => {
// 此处可以调用对应UI库 显示 loading
}
const loadingShow = () => {
// 此处可以调用对应UI库 隐藏 loading
}

function toPdf(imageList = [], fileName) {
  const doc = new JsPDF({
    orientation: 'l', // 页面方向,portrait: 纵向,landscape: 横向
    unit: 'mm',
    format: 'a5',
    putOnlyUsedFonts: true,
    floatPrecision: 16, // or "smart", default is 16
  }) // 以mm为单位


  imageList.forEach((imageItem, index) => {
    const width = doc.internal.pageSize.getWidth()
    const height = doc.internal.pageSize.getHeight()
    const widthRatio = width / imageItem.imgWidth
    const heightRatio = height / imageItem.imgHeight
    const ratio = Math.min(widthRatio, heightRatio)
    // 得到图片宽高
    const w = imageItem.imgWidth * ratio
    const h = imageItem.imgHeight * ratio
    const position = 0 // 页面偏移
    doc.addImage(imageItem.url, 'JPEG', 0, position, w, h)
    if (index < imageList.length - 1) {
      doc.addPage() // 添加新pdf页
    }
  })

  doc.save(fileName)
}

// 生成PPT
function toPPT(imageList = [], fileName) {
  const pptx = new pptxgen()
  imageList.forEach((imageItem) => {
    const slide = pptx.addSlide()
    let heightPercent = parseFloat(imageItem.imgHeight / imageItem.imgWidth * 100 * 16 / 9).toFixed(2)
    if (heightPercent > 100) {
      heightPercent = 100
    } else if (heightPercent < 30) {
      heightPercent = 30
    }
    slide.addImage({
      data: imageItem.url,
      x: 0,
      y: 0,
      w: '100%',
      // h: '100%',
      h: heightPercent + '%',
      sizing: { type: 'cover' }, // 图片尺寸contain
      // sizing: { type: "cover" }, // 图片尺
      align: 'center',
      fill: { color: 'F1F1F1' },
      color: 'A1A1A1',
    })
  })
  pptx.writeFile({ fileName })
}

// 生成文件
export async function generateFile({
  sourceList = [], // dom id 列表
  sourceType = 'DOM_ID_ARRAY', // DOM_ID_ARRAY | IMAGE_ARRAY
  exportType = 'ppt', // ppt | pdf
  name = '导出文件',
  antoDownload = true, // 是否自动下载
  showLoading = true, // 是否显示loading
}) {
  const fileName = `${name}-${dayjs().format('YYYYMMDDHHmmss')}`
  if (!sourceList?.length === 0)
    return console.log('exportToFile:导出数据源不能为空')
  if (showLoading) {
    loadingShow()
  }
  const imageList = []
  const imageListAsync = sourceList.map((domIDItem) => {
    const dom = document.getElementById(domIDItem)
    console.log('dom', domIDItem, dom)
    return html2canvas(dom, {
      scale: 2,
      backgroundColor: '#ffffff',
    })
  })

  Promise.all(imageListAsync).then((res) => {
    console.log('res', res)
    res.forEach((canvasItem) => {
      const chartImgUrl = canvasItem.toDataURL()
      if (!chartImgUrl) return
      imageList.push({
        url: chartImgUrl,
        imgWidth: canvasItem.width,
        imgHeight: canvasItem.height,
      })
    })
    if (exportType === 'ppt') {
      toPPT(imageList, `${fileName}.pptx`)
    }
    if (exportType === 'pdf') {
      toPdf(imageList, `${fileName}.pdf`)
    }
    if (showLoading) {
      loadingHide()
    }
  })
}