使用html2Canvas将html转png下载

121 阅读1分钟

主要步骤

  • 将页面元素转为图片
  • 图片拼接
  • 下载导出

主要代码

  • js文件
/*
 * @Description: html转PNG下载
 */
import html2Canvas from 'html2canvas';
import browserCheck from '@/Common/service/utils/browserCheck.js';
import i18n from '@/Common/i18n/index';

const pagePaddingLeft = 40;
const pagePaddingTop = 40;
const A4Height = 841.89;
const A4Width = 592.28;
const A4PageWidth = A4Width - 2 * pagePaddingLeft;
const A4PageHeight = A4Height - pagePaddingTop; 
const getCanvasByEl = (el, params = {}) => {
  return html2Canvas(el, {
    allowTaint: true,
    ...params
  });
};
const getImgByCanvas = (canvas) => {
  return new Promise((resolve) => {
    const img = new Image();
    img.src = canvas;
    if (!canvas || canvas === '') {
      resolve();
      return;
    }
    img.onload = () => {
      resolve(img)
    }
    img.onerror = () => {
      resolve(img)
    }
  });
};
const notIeDownloadImg = (dataURL, name) => {
  const anchor = document.createElement('a');
  anchor.style.display = 'none';
  anchor.href = dataURL;
  anchor.download = name;
  document.body.appendChild(anchor);
  doDownloadActive(anchor);
}

const doDownloadActive = (anchor) => {
  document.body.appendChild(anchor);
  const evt = document.createEvent('MouseEvents');
  evt.initEvent('click', true, true);
  anchor.dispatchEvent(evt);
  deleteDownloadDom(anchor);
}

const deleteDownloadDom = (anchor) => {
  document.body.removeChild(anchor);
}
const mergeImgCanvas = (imgList, { canvasWidth = A4Width } = {}) => {
  const imgTotalHeight = imgList.reduce((pre, cur) => pre + cur.imgHeight + cur.marginTop, 0);
  const canvas = document.createElement('canvas')
  canvas.width = canvasWidth;
  canvas.height = imgTotalHeight > A4PageHeight ? imgTotalHeight : A4PageHeight;
  const context = canvas.getContext('2d');
  context.fillStyle = '#fff';
  context.fillRect(0, 0, canvas.width, canvas.height);
  imgList.forEach(item => {
    context.drawImage(item.src, pagePaddingLeft, item.usedHeight + item.marginTop, item.imgWidth, item.imgHeight);
  });
  return canvas.toDataURL('image/jpeg', 1.0);
}
const ieDownloadImg = (dataUrl, name, type) => {
  const bstr = atob(dataUrl.split(',')[1]);
  // 获取解码后的二进制数据的长度,用于后面创建二进制数据容器
  const n = bstr.length;
  // 创建一个Uint8Array类型的数组以存放二进制数据
  const u8arr = new Uint8Array(n);
  // 将二进制数据存入Uint8Array类型的数组中
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  const blobObj = new Blob([u8arr]);
  if (type === 'png') {
    window.navigator.msSaveBlob(blobObj, name + '.png');
  } else if (type === 'jpg') {
    window.navigator.msSaveBlob(blobObj, name + '.jpg');
  }
}
const downloadImg = (dataUrl, fileName) => {
  if (browserCheck.isIE()) {
    ieDownloadImg(dataUrl, fileName);
  } else {
    notIeDownloadImg(dataUrl, fileName);
  }
};
const html2Img = async (elConfigs = [], fileName = '', isFitA4 = false) => {
  if (elConfigs.length === 0) {
    return;
  }
  let usedHeight = 0;
  const imgList = [];
  for (let i = 0; i < elConfigs.length; i++) {
    const config = elConfigs[i];
    const canvasRes = await getCanvasByEl(config.el, { scale: 1 });
    const img = await getImgByCanvas(canvasRes.toDataURL('image/jpeg', 1.0));
    let imgWidth = img.width;
    let imgHeight = img.height;
    // note 是否启用A4大小
    if (isFitA4) {
      let contentWidth = img.width;
      let contentHeight = img.height;
      imgWidth = A4PageWidth;
      imgHeight = (imgWidth / contentWidth) * contentHeight;
    }
    imgList.push({
      src: img,
      imgWidth,
      imgHeight,
      marginTop: config.marginTop,
      usedHeight
    })
    usedHeight = usedHeight + config.marginTop + imgHeight;
  }
  const canvasWidth = isFitA4 ? A4Width : imgList[0].imgWidth + 2 * pagePaddingLeft;
  const mergedImgDataUrl = mergeImgCanvas(imgList, { canvasWidth });
  const exportFileName = fileName ? `${fileName}.png` : `${i18n.t('hcp_disptchMng_heatmap_analysis')}_${new Date().format('yyyyMMddHHssmm')}.png`
  downloadImg(mergedImgDataUrl, exportFileName);
};
export {
  html2Img
};

  • vue文件
// 引入
import { html2Img } from '@/DispatchManagement/view/HeatMap/utils/html2Img.js';

//使用
 handleExport(exportType) {
      this.isExport = true;
      const exportDate = new Date();
      this.exportTime = exportDate.format('yyyy/MM/dd HH:mm:ss');
      const exportFileName =
        this.$t('hcp_disptchMng_heatmap_analysis') +
        exportDate.format('yyyyMMddHHssmm');
      this.$nextTick(async () => {
        const exportData = [
          { el: this.$refs.exportHeader, marginTop: 40 },
          { el: this.$refs.mapContainer, marginTop: 40 },
          { el: this.$refs.exportBottom, marginTop: 40 }
        ];
        exportType === 0
          ? await html2Pdf(exportData, exportFileName)
          : await html2Img(exportData, exportFileName);
        this.isExport = false;
        this.$emit('exportSuccess');
      });
    }