将html元素输出成图片/PDF

1,343 阅读3分钟

输出图片

使用html2canvas库

官方文档: html2canvas.hertzen.com

兼容: Firefox 3.5+/ Google Chrome/ Opera 12+/ IE9+/ Safari 6+

实现方案: html ——> canvas ——> image再下载或展示

使用bootstrap搭建一个demo,将测试数据的表格转换成图片

页面代码

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--The viewport meta tag is used to improve the presentation and behavior of the samples 
    on iOS devices-->
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
  <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <title></title>
</head>

<body>
  <div class="box" id='app'>
    <table class="table">
      <thead>
        <tr>
          <th>#</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Username</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">1</th>
          <td>Mark</td>
          <td>Otto</td>
          <td>@mdo</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
        </tr>
        <tr>
          <th scope="row">3</th>
          <td>Larry</td>
          <td>the Bird</td>
          <td>@twitter</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
        </tr>
      </tbody>
    </table>
    <button onclick="getImg()">截图</button>
    <img crossOrigin="anonymous" src="" id="showImg" alt="">
  </div>
  <script src="https://cdn.staticfile.org/jquery/3.5.1/jquery.js"></script>
  <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"
    integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous">
  </script>
  <script src="https://cdn.staticfile.org/html2canvas/0.5.0-beta4/html2canvas.js"></script>
  <script>
    function getImg() {
      html2canvas($(".table"),{
        background: "#fff",
      }).then(function (canvas) {
        // document.body.appendChild(canvas);
        var data = canvas.toDataURL("image/png")
        $("#showImg").attr('src', data)
      });
    }
  </script>

</html>

遇到的问题

  1. 移动端可能会模糊问题 可根据window.devicePixelRatio修改放大倍速
/**
     * 根据window.devicePixelRatio获取像素比
     */
    function DPR() {
      console.log(window.devicePixelRatio)
      if (window.devicePixelRatio && window.devicePixelRatio > 1) {
        // return window.devicePixelRatio;
      }
      return 1;
    }
    /**
     *  将传入值转为整数
     */
    function parseValue(value) {
      return parseInt(value, 10);
    };
    /**
     * 绘制canvas
     */
    async function drawCanvas(selector) {
      // 获取想要转换的 DOM 节点
      const dom = document.querySelector(selector);
      const box = window.getComputedStyle(dom);
      // DOM 节点计算后宽高
      const width = parseValue(box.width);
      const height = parseValue(box.height);
      // 获取像素比
      const scaleBy = DPR();
      // 创建自定义 canvas 元素
      const canvas = document.createElement('canvas');

      // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
      canvas.width = width * scaleBy;
      canvas.height = height * scaleBy;
      // 设定 canvas css宽高为 DOM 节点宽高
      canvas.style.width = `${width}px`;
      canvas.style.height = `${height}px`;
      // 获取画笔
      const context = canvas.getContext('2d');

      // 将所有绘制内容放大像素比倍
      context.scale(scaleBy, scaleBy);

      // 将自定义 canvas 作为配置项传入,开始绘制
      return await html2canvas(dom, {
        canvas,
        background: "#fff",
        useCORS: true
      });
    }
  1. 图片空白问题伙显示不全

    1. 容器内容过多,没有滚动到顶部导致显示不全问题,直接滚动到顶部即可
    window.pageYoffset = 0;
    
    document.documentElement.scrollTop = 0;
    
    document.body.scrollTop = 0;
    
    1. 跨域图片无法显示 配置useCORS: true 同时图片服务端设置允许跨域(返回 CORS 头)
    html2canvas($(".table"),{
        // 跨域图片配置
        useCORS: true
        background: "#fff",
    }).then(function (canvas) {
        // document.body.appendChild(canvas);
        var data = canvas.toDataURL("image/png")
        $("#showImg").attr('src', data)
    });
    

输出PDF

使用html2canvas+jsPdf库

jsPdf官方文档: parall.ax/products/js…

兼容: IE 10/ Firefox 3+/ Chrome/ Safari 3+/ Opera

实现方案: html ——> canvas ——> image ——> PDF下载

转化为图片使用html2canvas

图片转pdf代码

html2canvas(document.body, {
    onrendered: function (canvas) {
      var contentWidth = canvas.width;
      var contentHeight = canvas.height;
      //一页pdf显示html页面生成的canvas高度;
      var pageHeight = contentWidth / 592.28 * 841.89;
      //页面偏移
      //未生成pdf的html页面高度
      var leftHeight = contentHeight;
      var position = 0;
      //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
      var imgWidth = 595.28;
      var imgHeight = 592.28 / contentWidth * contentHeight;
      var pageData = canvas.toDataURL('image/jpeg', 1.0);
      var pdf = new jsPDF('', 'pt', 'a4');
      //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
      //当内容未超过pdf一页显示的范围,无需分页
      if (leftHeight < pageHeight) {
        pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
      } else {
        while (leftHeight > 0) {
          //arg3-->距离左边距;arg4-->距离上边距;arg5-->宽度;arg6-->高度
          pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
          leftHeight -= pageHeight;
          position -= 841.89; //避免添加空白页
          if (leftHeight > 0) {
            pdf.addPage();
          }
        }
      }
      pdf.save("test.pdf");
    },
    background: '#fff',
    useCORS: true,
    allowTaint: true,
    scale: window.devicePixelRatio,
    taintTest: false,
    width: w,
    height: h,
});

问题:

  1. 使用jspdf与seajs有冲突,暂无法使用
  2. 分页效果很差