Canvans生成图片踩坑记录

本文记录了一名开发者在使用HTML-Canvas实现截图功能时遇到的问题,如img标签生成空白、背景颜色调整和iframe截图难题。作者分享了针对性的解决策略,包括复制DOM处理、opacity转换和跨域通信协作等技巧。
摘要由CSDN通过智能技术生成

前记

很久之前为了完善运行时问题反馈体系开发了用户声音相关功能,其中有一个模块是截图生成当前图片并上传,作为一个开发老鸟,必须canvans搞一搞,找了现成的一套插件htmlcavans直接引入,这不是so easy,最终实现之后发现还是自己太年轻了,各种深渊大坑,特此记录一下踩坑之路。

问题

  • 1、生成图片的时候img标签生成失败显示空白
  • 2、弹出组件截图背景纯黑色或纯白色
  • 3、iframe生产失败,截图之后iframe区域显示空白

下面一一分析解决思路

生成图片的时候img标签生成失败显示空白

按照网上教程对htmlcavans进行各种设置,均未能解决该问题。所以剑走偏锋,在生成canvans的时候copy一份dom出来,然后将该dom下的img标签增加一个backgroundImg属性,copy一份的原因是防止更新影响原先视图,控制影响范围,下面直接上代码

 let cloneDome = document.cloneNode(true);
 let ImgList = cloneDome.querySelectorAll("img");
 //设置背景为实现截图
       for (let i = 0; i < ImgList.length; i++) {
         let src = ImgList[i].getAttribute("src");
         ImgList[i].style.backgroundImage = ` url(${src})`;
         ImgList[i].style.backgroundSize = "100%";
       }
 return new html2canvas(cloneDome.body, {
   ....
 })
弹出组件截图背景纯黑色或纯白色 (慎用!)

这个问题也困扰了一段时间,经过排查是对opacity属性支持有问题导致,处理方案在生成图片是同样对copy的dom进行操作,转换为rgba背景色实现类似透明度效果,不过该方案可能存在误杀谨慎使用

let cloneDome = document.cloneNode(true);
//由于批量处理存在风险,此处只处理需要处理的dom
if(cloneDome.querySelector("******")){
  cloneDome.querySelector("******").style.opacity = 1;
  cloneDome.querySelector("******").style.backgroundColor =
         "rgba(0,0,0,0.5)";
 return new html2canvas(cloneDome.body, {
   ....
 })
}
iframe生产失败,截图之后iframe区域显示空白

iframe生成图片失败,一开始我们认为是domain不同导致的跨域问题,但是调整domin之后依然失败,问题又回来了,和组大牛讨论之后决定采用一个比较骚的套路具体实现是:在生成图片之前如果存在iframe则主页面给iframe发送消息,在iframe内自截图生成图片并传递给主页面,主页面合并图片,但是合并图片存在一些问题,最棘手的就是合并的位置如何计算获取,转念一想没必要去自己计算直接给iframe设置背景图片就完美的解决了最棘手的合并位置问题,代码如下:
(ps:该方案默认只存在一个iframe下,多个iframe由于性能等问题暂不考虑,多个iframe支持情况可以自行修改代码)

 //如果存在ifram======等待生成ifram的图片
            let ifram = cloneDome.querySelector("iframe");
            let promiseProxy=""
            if (
              ifram &&
              ifram.getAttribute("src").indexOf("fas.teld.org") != -1
            ) {
              promiseProxy = new Promise((resolve)=>{
                window.onmessage = (e) => {
                  if (e.data.type == "ScreenshotResult") {
                    ifram.style.backgroundSize = "100%";
                    ifram.style.backgroundImage = ` url(${ e.data.data})`;
                    resolve()
                  }
                  
                };
                //消息失败超时自动放行,防止页面卡死
                setTimeout(() => {
                  resolve()
                }, 10000);
              })
             
              ifram.contentWindow.postMessage({ type: "Screenshot" }, "*");

            }
            if(promiseProxy){
                 await promiseProxy
             }
            return new html2canvas(cloneDome.body, {
              ....
            })
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值