星期
纯前端导出带水印文件
首页 > 我的学习历程    作者:月丶   2023年11月20日 15:25 星期一   热度:293°   百度已收录  
时间:2023-11-20 15:25   热度:293° 
1、安装依赖
npm install exceljs file-saver html2canvas jspdf

2、导出方法
可导出图片,Excel文件
import htmlTocanvas from 'html2canvas'
import ExcelJS from 'exceljs'
import jsPDF from 'jspdf'
import { saveAs } from 'file-saver'
export const ExportUtil = {
  /**
   * Generates a function comment for the given function body in a markdown code block with the correct language syntax.
   *
   * @param {Object} options - An object containing the function parameters.
   * @param {string} options.name - The name of the export.
   * @param {Array} options.data - The data to be exported.
   * @param {Array} options.columns - The columns to be included in the export.
   * @param {string} options.waterText - The watermark text to be added to the export.
   * @return {undefined} This function does not return a value.
   */
  exportExcel ({ name = `${new Date().getTime()}`, data = [], columns = [], mergeColumns = [], waterText = true }) {
    const workbook = new ExcelJS.Workbook()
    const worksheet = workbook.addWorksheet('sheet1')
    if (waterText) {
      const defaultText = '测试水印'
      waterText = typeof waterText === 'string' ? waterText : defaultText
      const base64Img = this.setWatermark(waterText)
      const img = workbook.addImage({
        base64: base64Img,
        extension: 'png'
      })
      worksheet.addBackgroundImage(img)
    }

    if (columns && columns.length) {
      // 设置列头
      const columnsData = columns.map((column) => {
        return {
          header: column.title,
          key: column.dataIndex || column.field,
          style: {
            alignment: { horizontal: 'center', vertical: 'middle' }
          },
          width: 20
        }
      })
      worksheet.columns = columnsData
    }
    if (mergeColumns && mergeColumns.length) {
      // 设置合并的表头
      mergeColumns.forEach(item => {
        const start = item.mergeCells.split(':')[0]
        worksheet.mergeCells(item.mergeCells)
        worksheet.getCell(start).value = item.value
        worksheet.getCell(start).alignment = { horizontal: 'center', vertical: 'middle' }
        worksheet.getCell(start).font = { bold: true }
      })
    }

    // 将 JSON 数据转换为工作表的行
    worksheet.addRows(data)
    workbook.xlsx.writeBuffer().then((res) => {
      saveAs(new Blob([res], { type: 'application/octet-stream' }), name.includes('.xlsx') ? name : `${name}.xlsx`)
    })
  },
  exportPDF ({ element, fileName, config = {}, waterText = true }) {
    return new Promise((resolve, reject) => {
      htmlTocanvas(element, {
        useCORS: true,
        backgroundColor: '#f7f7f8',
        ...config
      }).then(canvas => {
        let base64Img
        if (waterText) {
          const userInfo = store.getters.userInfo
          const defaultText = '测试水印'
          waterText = typeof waterText === 'string' ? waterText : defaultText
          base64Img = this.setWatermark(waterText, canvas)
        }
        const imgData = base64Img || canvas.toDataURL('image/png')
        const pdf = new jsPDF('p', 'pt', 'a4')
        // 获取PDF页面的宽度和高度
        const pdfWidth = pdf.internal.pageSize.getWidth()
        const pdfHeight = pdf.internal.pageSize.getHeight()
        // 计算图像的缩放比例,使其铺满整个PDF页面
        const imgWidth = pdfWidth
        const imgHeight = (imgWidth * pdfHeight) / pdfWidth
        pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight)
        pdf.save(fileName.includes('.pdf') ? fileName : `${fileName}.pdf`)
        resolve()
      }).catch(err => {
        reject(err)
      })
    })
  },
  /**
   * Takes an HTML element and converts it to a canvas image, optionally adding a watermark text.
   *
   * @param {object} options - An object containing the following properties:
   *   @param {HTMLElement} options.element - The HTML element to convert to canvas.
   *   @param {string} options.fileName - The name of the file to be downloaded.
   *   @param {object} [options.config={}] - Additional configuration options for the HTML to canvas conversion.
   *   @param {boolean} [options.waterText=true] - Whether to add a watermark text to the image.
   * @return {Promise} A Promise that resolves when the image is downloaded.
   */
  exportImg({ element, fileName, config = {}, waterText = true }) {
    return new Promise((resolve, reject) => {
      htmlTocanvas(element, {
        useCORS: true,
        backgroundColor: '#f7f7f8',
        ...config
      }).then(canvas => {
        let base64Img
        if (waterText) {
          const defaultText = '测试水印'
          waterText = typeof waterText === 'string' ? waterText : defaultText
          base64Img = this.setWatermark(waterText, canvas)
        }
        const link = document.createElement('a')
        link.download = `${fileName || new Date().getTime()}.png`
        link.href = base64Img || canvas.toDataURL('image/png')
        link.click()
        resolve()
      }).catch(err => {
        reject(err)
      })
    })
  },
  /**
  * Sets a watermark on a canvas.
  * 如果是导出图片的话,必传canvas,导出excel的时候不需要传
  *
  * @param {string} str - The text of the watermark.
  * @param {HTMLCanvasElement} canvas - The canvas element to place the watermark on. If not provided, a new canvas will be created.
  * @return {string} - The data URL of the canvas with the watermark.
  */
  setWatermark (str, canvas) {
    // 创建一个画布
    let can = canvas || document.createElement('canvas')
    if (!canvas) {
      // 设置画布的长宽
      can.width = 500
      can.height = 400
    }
    let ctx = can.getContext('2d')
    ctx.font = '18px Vedana'
    // 设置填充绘画的颜色、渐变或者模式
    ctx.fillStyle = 'rgba(130, 142, 162, 0.5)'
    // 旋转角度
    ctx.rotate(-60 * Math.PI / 220)
    // 设置文本内容的当前对齐方式
    ctx.textAlign = 'left'
    // 设置在绘制文本时使用的当前文本基线
    ctx.textBaseline = 'Middle'

    if (canvas) {
      // 定义水印的间隔和偏移量
      const xOffset = -can.width / 2 // X轴偏移量
      const yOffset = -can.height / 2 // Y轴偏移量

      // 循环绘制水印文本
      for (let x = 0; x < can.width * 1.5; x += 400) {
        for (let y = 0; y < can.height * 1.5; y += 300) {
          ctx.fillText(str, x + xOffset, y + yOffset)
        }
      }
    } else {
      let initY = can.height
      ctx.fillText(str, 0, initY)
    }

    return can.toDataURL('image/png')
  }
}

3、使用
import ExportUtil from 'xxx'

ExportUtil.exportExcel({name: '导出文件',columns:[{field: test,title: 测试头}],data:[{test: 23}]})
ExportUtil.exportPDF({element: element, name:'导出PDF'})
ExportUtil.exportImg({element: element, name:'导出图片'})

二维码加载中...
本文作者:月丶      文章标题: 纯前端导出带水印文件
本文地址:http://silver.eleuu.com/?post=51
版权声明:若无注明,本文皆为“月丶”原创,转载请保留文章出处。

返回顶部    手机版本    会员注册   
版权所有:月丶    博主: 月丶    团队首页电子乌托邦  博客框架:emlog   蜀ICP备18008322号   
  
//音乐播放器