Vue使用html2canvas与jspdf下载图片和pdf

1,363 阅读2分钟

准备工作

安装依赖
npm install html2canvas jspdf --save
引入依赖
import html2canvas from "html2canvas"
import jsPDF from "jspdf"

以下为使用实例

页面DOM结构

<div class="printmain" ref="printPdf" >
<table border="1">
<tr>
<td rowspan="3"></td>
<td colspan="4" class="middle">推广合作执行单</td>
</tr>
<tr>
<td colspan="4" class="tr">编号:</td>
</tr>
<tr>
<td style="width: 120px;" class="bold">乙方:</td>
<td ></td>
<td style="width: 120px;" class="bold">甲方:</td>
<td ></td>
</tr>
<tr>
<td rowspan="17"></td>
<td colspan="4">结算明细</td>
</tr>
<tr>
<td colspan="4" style="padding:0;">
<table class="border-in">
<tr>
<td style="width:120px;">渠道名称</td>
<td>渠道ID</td>
<td>计费方式</td>
<td>单价</td>
<td>数量</td>
<td>结算金额</td>
<td>备注(期间)</td>
</tr>
<tr>
<td>1</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="2">总计</td>
<td colspan="2">0</td>
</tr>
<tr>
<td colspan="2">大写</td>
<td colspan="2" class="tl">人民币:</td>
</tr>
<tr>
<td colspan="4" style="background:#ccc" class="bold">收款方(乙方)信息</td>
</tr>
<tr>
<td style="width: 120px;">公司名称</td>
<td></td>
<td style="width: 120px;">银行账号</td>
<td></td>
</tr>
<tr>
<td style="width: 120px;">开户行</td>
<td></td>
<td style="width: 120px;">发票税率</td>
<td>6%</td>
</tr>
<tr>
<td style="width: 120px;">发票类型</td>
<td>增值税专用发票</td>
<td style="width: 120px;">开票内容</td>
<td>信息服务费</td>
</tr>
<tr>
<td colspan="4" style="background:#ccc" class="bold">付款方(甲方)信息</td>
</tr>
<tr>
<td style="width: 120px;">公司名称</td>
<td></td>
<td style="width: 120px;">开户银行</td>
<td></td>
</tr>
<tr>
<td style="width: 120px;">纳税人识别号</td>
<td></td>
<td style="width: 120px;">账号</td>
<td>6%</td>
</tr>
<tr>
<td style="width: 120px;">开票地址</td>
<td>增值税专用发票</td>
<td style="width: 120px;">电话</td>
<td>信息服务费</td>
</tr>
<tr>
<td colspan="4" style="background:#ccc" class="bold">本结算双方盖章后生效,付款方需执 贰 份</td>
</tr>
<tr>
<td colspan="4" style="background:#ccc" class="bold">本期结算单价以双方盖章确认的结算单上的单价为准</td>
</tr>
<tr>
<td colspan="2" class="bold"></td>
<td colspan="2" class="bold">新浪爱问普惠</td>
</tr>
<tr style="height:100px;">
<td colspan="2" >收款方(乙方)盖章</td>
<td colspan="2">付款方(甲方)盖章</td>
</tr>
<tr>
<td colspan="2" >日期:</td>
<td colspan="2" >日期:</td>
</tr>
</table>
</div>
<button type="danger" @click="canvas">test</button>

执行函数块逻辑

canvas(){
  // this.$refs.printPdf  获取需要绘图的区域
  html2canvas(this.$refs.printPdf,{scale: 2,dpi: 144,}).then(canvas => {
  	var context = canvas.getContext('2d')
    //以下content关闭抗锯齿
    context.mozImageSmoothingEnabled = false;
    context.webkitImageSmoothingEnabled = false;
    context.msImageSmoothingEnabled = false;
    context.imageSmoothingEnabled = false;
	document.body.appendChild(canvas); // 图片插入到页面
    //生成图片处理
    var imgUri = canvas.toDataURL();
    var type = 'png';
    var imgData = canvas.toDataURL(type);
    var _fixType = function(type) {
      type = type.toLowerCase().replace(/jpg/i, 'jpeg');
      var r = type.match(/png|jpeg|bmp|gif/)[0];
      return 'image/' + r;
    };
    imgData = imgData.replace(_fixType(type),'image/octet-stream');
    var saveFile = function(data, filename){  //保存图片处理函数
      var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
      save_link.href = data;
      save_link.download = filename;
      var event = document.createEvent('MouseEvents');
      event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, 			false, 0, null);
      save_link.dispatchEvent(event);
  };
  	saveFile(imgData,'结算执行单.png');


    //保存为pdf处理
    var contentWidth = canvas.width;
    var contentHeight = canvas.height;
    var pageHeight = contentWidth / 592.28 * 841.89;
    var leftHeight = contentHeight;
    //页面偏移
    var position = 0;
    //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
    var imgWidth = 595.28;
    var imgHeight = 595.28 / contentWidth * contentHeight;

    var pageData = canvas.toDataURL('image/jpeg', 1.0);
    var pdf = new jsPDF('', 'pt', 'a4');

    //放大会清晰一点
    pdf.internal.scaleFactor = 1.5;
    //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
    //当内容未超过pdf一页显示的范围,无需分页
    if (leftHeight < pageHeight) {
		pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
	} else {
	while (leftHeight > 0) {
		pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
		leftHeight -= pageHeight;
		position -= 841.89;
		//避免添加空白页
		if (leftHeight > 0) {
			pdf.addPage();
		}
	}
  }
	pdf.save('stone.pdf');
})

CSS样式 (canvas生存的区域必须是可见区域 不能绘制隐藏的内容,因此需要先显示页面,在图片生成后再隐藏

.printmain {
  position: fixed;//脱离文档 不占空间;
  z-index: -1; //设置为不可见;
  width: 600px;
  padding: 0.5px;
}