月丶
纯前端导出带水印文件
2023-11-20 月丶
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:'导出图片'})

发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容