引子

产品的需求是这样,要保存当前页面为一张图片。商户需要下载这张图片,并打印。

一个库

html2canvas

js将遍历加载页面的 DOM 节点,收集所有元素的信息,然后用这些信息来呈现页面。换句话说,实际上这个库并不是真的对页面进行截图,而是基于从 DOM 读取的元素及属性来一点点的绘制 canvas。 因此,它只能正确地呈现它理解的元素和属性,这意味着有许多 CSS 属性不起作用。

图片模糊问题

移动端像素密度计算的问题

html2canvas支持自定义 canvas 作为配置项传入了,它会根据我们传入的 canvas 为基础开始绘制。所以我们在调用 html2canvas 的时候,可以先创建好一个尺寸合适的 canvas,再传进去。

重要的是设置合适的宽高

  • 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
  • 设定 canvas css宽高为 DOM 节点宽高
  • 将所有绘制内容放大像素比倍 scale
  1. /**
  2. * 绘制canvas
  3. */
  4. async function drawCanvas(selector) {
  5. // 获取想要转换的 DOM 节点
  6. const dom = document.querySelector(selector);
  7. const box = window.getComputedStyle(dom);
  8. // DOM 节点计算后宽高
  9. const width = parseValue(box.width);
  10. const height = parseValue(box.height);
  11. // 获取像素比
  12. const scaleBy = DPR();
  13. // 创建自定义 canvas 元素
  14. const canvas = document.createElement('canvas');
  15. // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
  16. canvas.width = width * scaleBy;
  17. canvas.height = height * scaleBy;
  18. // 设定 canvas css宽高为 DOM 节点宽高
  19. canvas.style.width = `${width}px`;
  20. canvas.style.height = `${height}px`;
  21. // 获取画笔
  22. const context = canvas.getContext('2d');
  23. // 将所有绘制内容放大像素比倍
  24. context.scale(scaleBy, scaleBy);
  25. // 将自定义 canvas 作为配置项传入,开始绘制
  26. return await html2canvas(dom, {canvas});
  27. }
  28. 作者:丁香园F2E
  29. 链接:https://juejin.im/post/5a17c5e26fb9a04527254689
  30. 来源:掘金
  31. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

污染的画布

HTML 规范中图片有一个 crossorigin 属性,结合合适的 CORS 响应头,就可以实现在画布中使用跨域 屏幕截图实战 - 图1 元素的图像。

  1. 图片的域名要返回跨域头
  2. html2canvas(dom, {canvas, useCORS: true})

canvas生成dataUrl

所以需要将canvas生成dataUrl

canvas.toDataURL(‘image/png’)

dataUrl to file blob

  1. function dataURLtoBlob(data) {
  2. var mimeString = data.split(',')[0].split(':')[1].split(';')[0]
  3. var byteString = atob(data.split(',')[1])
  4. var ab = new ArrayBuffer(byteString.length)
  5. var ia = new Uint8Array(ab)
  6. for (var i = 0; i < byteString.length; i++) {
  7. ia[i] = byteString.charCodeAt(i)
  8. }
  9. var bb = (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)
  10. if (bb) {
  11. bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)()
  12. bb.append(ab)
  13. return bb.getBlob(mimeString)
  14. } else {
  15. bb = new Blob([ab], {
  16. 'type': (mimeString)
  17. })
  18. return bb
  19. }
  20. }

file blob 下载

图片的url需要上传的OSS上之后,才会有。因此,需要先上传的OSS,调用app的接v3/upload接口可以上传图片,但是必须是file对象 得到图片的域名

下载图片

利用bridge的download方法,接受一个url