Html2canvas——图片空白的几种排查解决方案

  • Html2canvas——图片空白的几种排查解决方案已关闭评论
  • 55 次浏览
  • A+
所属分类:Web前端
摘要

  下列文章来源该篇 html2canvas库的工作原理并不是真正的“截图”,而是读取网页上的目标DOM节点的信息来绘制canvas,所以它并不支持所有的css属性。

问题:用html2canvas生成画布图片,再转成pdf。生成图片时内容结构里的图片显示空白。 解决: 首先服务器设置图片允许跨域,如阿里云腾讯云配置跨域规则。其次图片设置crossOrigin=“anonymous”,并且拿到图片地址加随机参数如 src +‘?v=’ + Math.random()防止使用缓存,再者html2canvas设置属性useCORS, allowTaint为true。 

  下列文章来源该篇

 

一、工作原理

html2canvas库的工作原理并不是真正的“截图”,而是读取网页上的目标DOM节点的信息来绘制canvas,所以它并不支持所有的css属性

二、在 img标签中加载外部图片

前提是外部图片允许跨域,需要服务器设置

以nginx为例,response-header内要存在Access-Control-Allow-Orgin:xxxx(可以是*,安全性要求比较高的可以根据主域名自定义),如果该资源所在的web-server是不支持跨域的,保存图片是不会成功的。

img标签设置跨域

当html2canvas中生成的截图中包含外部图片,那么外部图片在引入的时候就需要设置允许跨域。

另外,通过 ‘img’ 加载的图片,浏览器默认情况下会将其缓存起来,在canvas中用到图片时,就会直接使用缓存图片,不会再重新发请求。又因为浏览器本身不会有跨域问题,所以如果‘img’没有设置 crossorigin 属性,那么就会出现跨域问题,图片不能再次被复用到 canvas 上去的。

1. 'img’标签设置crossOrigin属性
<img crossOrigin="anonymous" src={imgSrc} alt="img" />

这是最简单的方法,让图片可以复用到canvas上。

2. chrome设置
<img src={imgSrc} alt="img" />

浏览器设置 disable cache,这种方法需要设置浏览器属性,不推荐。

Html2canvas——图片空白的几种排查解决方案

 

3. 使用JS加载图片
const [imgBase, setImgBase] = useState(""); <img src={imgBase} alt="img" />   const downloadIamge = imgsrc => {     //下载图片地址和图片名     let image = new Image();     // 解决跨域 Canvas 污染问题     image.setAttribute("crossOrigin", "anonymous");     image.onload = function() {       let canvas = document.createElement("canvas");       canvas.width = image.width;       canvas.height = image.height;       let context = canvas.getContext("2d");       context.drawImage(image, 0, 0, image.width, image.height);       let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据       setImgBase(url);     };     image.src = imgsrc;   };

 

这种方法能避免使用图片缓存,在开发过程中,使用js方式请求图片资源,最好每一次都加个随机数,以保证源都是最新的,不走缓存。

三、在 html2canvas 中使用
 const createImg = async id => {      const dom = document.getElementById(id);      const config = {           useCORS: true,           width: dom.offsetWidth,           height: dom.offsetHeight,           scrollX: 0,           scrollY: 0,           x: 0,           y: 0,         }; const data = await html2canvas(dom, config).then(canvas =&gt; {   canvas.id = "mycanvas";    document.body.appendChild(canvas);   const mycanvas = document.getElementById("mycanvas");   mycanvas.style.display = "none";   mycanvas.style.position = "fixed";   mycanvas.style.top = "0px";   mycanvas.style.left = "0px";   mycanvas.style.zIndex = "9999";    let imgData = mycanvas.toDataURL("png");   imgData = imgData.replace(fixType("png"), "image/octet-stream");   const file = dataURLtoFile(imgData, "poster.png");    return file; });  return data; };

 

四、html2canvas设置

使用外部图片就会面临跨域的问题,html2canvas也需要设置属性。

1. 允许画布图片跨域
confit = { useCORS: true }

 

2. 允许外部图片污染画布
confit = { allowTaint: true } 

 

使用上面两种方法就可以让外部图片显示在画布上,虽然方法2可以让外部图片显示在画布上,但是却不能调用 toBlob(), toDataURL() 或 getImageData() 方法,调用它们会抛出安全错误。

五、可能出现的问题
1. html2canvas生成的图片无法显示

可能是使用缓存图片,有以下解决方法

  • 在 Chrome 的调试器中,在 network 面板中,勾选 disable cache 选项,再重新加载图片
  • 图片的访问地址加个随机数
  • 将图片url转成base64
2. html2canvas生成的图片显示空白

如果是出现了空白,那有可能是转成图片的部分出现滚动条且是在弹窗中展示,需要设置相关滚动高度。
或者有可能是dom不对,请保证dom是要截图那个元素的父元素

 const dom = document.getElementById(id);  const config = {     useCORS: true,     windowHeight:modal.scrollHeight + 24 + 100,//获取y方向页面包含滚动条的高度,24和100为padding,margin     width: dom.offsetWidth + 48,//48为padding值     height: dom.clientHeight + 400,//可见高度+padding+margin     y: window.pageYOffset + 100,//滚动条高度修复     scrollX: 17  };

 

3. ‘img’ 加上crossOrigin="anonymous"之后图片无法显示

这个有可能是浏览器缓存导致了,可以试试重新加载资源,也可以在资源的请求路径后加上时间戳重新加载。

六、参考
  1. 中文文档
  2. canvas.toDataURL()报错的解决方案全都在这了
  3. 一个关于image访问图片跨域的问题
  4. canvas.toDataURL()报错的解决方案全都在这了
  5. html2canvas生成图片
  6. html2canvas截图空白问题
  7. html2canvas生成pdf页面空白
  8. 基于html2canvas实现网页保存为图片及图片清晰度优化