前段时间有个需求,想要 打印一个小票凭证 ,实现这个功能,我首先想到了快照,
就是将数据内容排版好,然后截图或者用其他方式将内容 制作成图片 ,然后下载下来打印即可。
为何不直接以文件的形式打印呢?原因是用文件排版【包含文字和图片内容】,太复杂了,效果和稳定性不确定,还不如用快照,简单省事,效果也好。
【图一】输入动态数据
【图二】js排版,放在一个div里面
【图三】触发生成快照并网页本地下载 ,【如果是要分享,则将图片上传服务器,存储后,获取访问该图片的网址路径,将路径分享即可】
【图四】本地下载的图片文件
【图五】
效果如何?我觉得挺好的,二维码是我后台生成的,用路径获取即可
其实这都多亏了html2canvas库 ,这是一个js版本操作画布canvas的一个集成库,调用api设置参数即可自定义内容,
问题是,直接使用html2canvas 会导致内容模糊、字迹不清晰等问题,还需要其他的辅助算法才可以制作清晰的快照。
我结合layerUi.js框架做了一个弹窗,动态编辑内容
1 //显示需要打印的数据 ,参数分别是 医院全称,订单id ,用户姓名 ,二维码图片路径 2 function showPrintData(hname, oid, time, name, qrurl,sName,fee) { 3 //显示信息 4 let text = ‘<div style="text-align: center;padding: 10px">‘ + 5 ‘<div id="qrMy" style="display: inline-block;text-align: left;background-color: white;">‘ + 6 ‘<div style="padding: 10px">‘ + 7 ‘<div>医院名称:‘ + hname + ‘</div>‘ + 8 ‘<div>预约订单id:‘ + oid + ‘</div>‘ + 9 ‘<div>科目:‘ + sName + ‘</div>‘ +10 ‘<div>预约时间:‘ + time + ‘</div>‘ +11 ‘<div>挂号金额:‘ + fee + ‘ 元</div><hr>‘ +12 ‘<div>姓名:‘ + name + ‘</div>‘ +13 ‘<div style="padding: 10px">‘ +14 ‘<img src="‘ + basePath + qrurl + ‘" alt="二维码"></div>‘ +15 ‘</div></div></div>‘;16 layer.open({17 type: 1,18 title:"快照预览",19 skin: ‘layui-layer-rim‘, //加上边框20 offset: popupTop + "px",21 area: [popupWidth + ‘px‘, popupHeight + ‘px‘],22 content: text,23 closeBtn: 0,24 btn: ‘打印并完成业务‘,25 yes: function (index, layero) {26 //下载截图27 doLoadQR(name);28 layer.close(index);29 },30 });31 //按钮点击打印即可关闭32 isDoOrderOkOnce = false;33 }
View Code
有 id="qrMy" 的div是关键 ,该库将会作用在这个div里面
触发生成快照
1 //本地下载快照 ,name是文件的部分名称 2 function doLoadQR(name) { 3 //新建一个画布元素 4 let canvas2 = document.createElement("canvas"); 5 //获取该元素区块的本身宽高 6 let w = parseInt($(‘#qrMy‘).width()); 7 let h = parseInt($(‘#qrMy‘).height()); 8 // console.log(w+"======"+h); 9 //因为直接用默认画布会模糊,因此自定义画布,设置画布尺寸为容器的两倍大小,再将内容放大两倍画上去,10 // 修改偏移量,就可以解决模糊问题11 //画布真实宽高12 canvas2.width = w * 2;13 canvas2.height = h * 2;14 //宽高宽高15 canvas2.style.width = w + "px";16 canvas2.style.height = h + "px";17 //设置画布的内容18 let context = canvas2.getContext("2d");19 //x,y轴放大两倍20 context.scale(2, 2);21 //获取容器边距对象22 let rect = $(‘#qrMy‘).get(0).getBoundingClientRect();23 //设置偏移量24 context.translate(‘-‘ + rect.left, ‘-‘ + rect.top);25 //调用库26 html2canvas(document.querySelector(‘#qrMy‘)27 , {28 useCORS: true,29 scale: 2,30 width: w,31 height: h,32 //使用自定义的画布33 canvas: canvas2,34 // window.devicePixelRatio是设备像素比35 dpi: window.devicePixelRatio * 2,36 37 }38 ).then(function (canvas) {39 // 回调生成的画布canvas对象40 // 获取生成的图片的相对url,其实将bese64加密的数据 的数据类型image/png换成image/octet-stream41 let imgUri = canvas.toDataURL("image/png")42 .replace("image/png", "image/octet-stream");43 //文件名称44 let filename = (new Date()).getTime() + "_" + name + ‘.png‘;45 //下载46 saveFile(imgUri, filename);47 });48 }
View Code
//
如何自定义本地下载?
其实就是用<a>,模拟点击即可
1 // * 在本地进行文件保存 2 // * @param {String} data 要保存到本地的图片数据/或路径 3 // * @param {String} filename 文件名 4 // */ 5 function saveFile(data, filename) { 6 // 创建一个<a>标签 7 let save_link = document.createElement(‘a‘); 8 save_link.href = data; 9 save_link.download = filename;10 let event = document.createEvent(‘MouseEvents‘);11 event.initMouseEvent(‘click‘, true, false, window, 0,12 0, 0, 0, 0, false, false,13 false, false, 0, null);14 save_link.dispatchEvent(event);15 }
View Code