引子
产品的需求是这样,要保存当前页面为一张图片。商户需要下载这张图片,并打印。
一个库
html2canvas
js将遍历加载页面的 DOM 节点,收集所有元素的信息,然后用这些信息来呈现页面。换句话说,实际上这个库并不是真的对页面进行截图,而是基于从 DOM 读取的元素及属性来一点点的绘制 canvas。 因此,它只能正确地呈现它理解的元素和属性,这意味着有许多 CSS 属性不起作用。
图片模糊问题
移动端像素密度计算的问题
html2canvas支持自定义 canvas 作为配置项传入了,它会根据我们传入的 canvas 为基础开始绘制。所以我们在调用 html2canvas 的时候,可以先创建好一个尺寸合适的 canvas,再传进去。
重要的是设置合适的宽高
- 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
- 设定 canvas css宽高为 DOM 节点宽高
- 将所有绘制内容放大像素比倍 scale
/*** 绘制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});}作者:丁香园F2E链接:https://juejin.im/post/5a17c5e26fb9a04527254689来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
污染的画布
HTML 规范中图片有一个 crossorigin 属性,结合合适的 CORS 响应头,就可以实现在画布中使用跨域
元素的图像。
- 图片的域名要返回跨域头
- html2canvas(dom, {canvas, useCORS: true})
canvas生成dataUrl
所以需要将canvas生成dataUrl
canvas.toDataURL(‘image/png’)
dataUrl to file blob
function dataURLtoBlob(data) {var mimeString = data.split(',')[0].split(':')[1].split(';')[0]var byteString = atob(data.split(',')[1])var ab = new ArrayBuffer(byteString.length)var ia = new Uint8Array(ab)for (var i = 0; i < byteString.length; i++) {ia[i] = byteString.charCodeAt(i)}var bb = (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)if (bb) {bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)()bb.append(ab)return bb.getBlob(mimeString)} else {bb = new Blob([ab], {'type': (mimeString)})return bb}}
file blob 下载
图片的url需要上传的OSS上之后,才会有。因此,需要先上传的OSS,调用app的接v3/upload接口可以上传图片,但是必须是file对象 得到图片的域名
下载图片
利用bridge的download方法,接受一个url
