我妈已经三天没打我了 2026-03-26 11:06 采纳率: 86.1%
浏览 5

html2canvas屏幕截图一直显示为空白?

img

img

弹框样式内容先显示了,然后过了一秒变成空白的img



.ewm{
    background: linear-gradient( 355deg, #D4F2FF 0%, #EBFFFF 100%);
    padding-bottom: 0.8rem;
  visibility: visible;
  position: static;
}
.erwm .ewm_pname{
    font-weight: 600;
    font-size: 0.72rem;
    color: #167AFF;
    text-align: center;
    height: 2.4rem;
    line-height: 3rem;
    width: 100%;
    background: url(../images/ewm_bg.png) no-repeat;
  background-size: 100% 100%;
    margin-bottom: .72rem;
}
#output {
    background: url(../images/ewm_line.png) no-repeat;
    background-size: 100% 100%;
    padding: .56rem .78rem 0rem;
    border: none;
    /* padding-bottom: 0.8rem; */
}
#output .outputline{
    padding: .56rem;
    background-color: #FFFFFF;
    border-radius: 0.2rem;
}
#output p{
    font-weight: 400;
    font-size: .48rem;
    color: #010002;
    line-height: .78rem;
    margin-top: .6rem;
    text-align: center;
}
#desc{
    margin-top: .28rem;
}

.ewm_info,.ewm_add{
    background-color: #FFFFFF;
    width: 92%;
    margin: 0 auto;
    display: flex;
    padding: .32rem 0.2rem 0.32rem 1rem;
    box-sizing: border-box;
    font-size: .48rem;
  line-height: .7rem;
    text-align: left;
    border-radius: .38rem;
}
.ewm_add{
    flex-wrap: wrap;
    gap: 10px;
  color: #167AFF;
}

.ewm_add .ewm_addxing {
    flex: 1 0 calc(40%);
    box-sizing: border-box;
    margin: 0;
    min-width: 0;
  display: flex;
    align-items: center;
}
.ewm_addxing{
    
}
.ewm_addcalc{
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #2FAEFF;
    margin-right: .4rem;
}
.ewm_info{
    flex-direction: column;
    margin-top: .4rem;
    margin-bottom: .8rem;
    color: #444444;
}
.ewm_info_addxing{
    display: flex;
    align-items: center;
}
.qr_suspend {
    padding-top: 16% !important;
}
<div class="fr common_right_btn" onclick="savePlan()" v-show="!role">分享</div>
$("#mask").before('<div class="qr_suspend"><div class="con_qr"><img id="my_close" src="../../images/icon_myclose.png" alt=""><div class="erwm"><p class="ewm_pname"></p><div class="ewm_add"><div class="ewm_addxing"><div class="ewm_addcalc"></div><p class="ewm_addcalc_name"></p></div></div><div class="ewm_info"><div class="ewm_info_addxing"><div class="ewm_addcalc"></div><p>交费期:<span class="ewm_num"></span></p></div><div class="ewm_info_addxing"><div class="ewm_addcalc"></div><p>保额:<span class="ewm_amount"></span>元</p></div><div class="ewm_info_addxing"><div class="ewm_addcalc"></div><p>首年合计保费:<span class="ewm_premium"></span>元</p></div></div><div id="output"><div class="outputline"><img id="qrcodeimg" src=""><div id="qrcode"></div></div><p>投保链接</p></div></div><p class="copy-links"><span class="btn copy-button" data-clipboard-text="1">复制链接</span></p><p id="desc">长按保存或者转发给客户,建议不要直接<br>扫码,防止中途退出投保,找不到入口</p></div></div>')//20260212-6236二维码生成
// 引入二维码/复制插件
document.write("<script src='../../lib/html2canvas1.0.0.js?v=1.34'></script>");
document.write("<script src='../../lib/jquery.qrcode.min.js?v=1.34'></script>");
document.write("<script src='../../lib/clipboard.min.js'></script>");
document.write("<script src='../../js/common/wxxcx.js?v=2019.11.21.18'></script>");
// 主界面
function savePlan() {
    link = commonurl_front  + "&seed_no=" + return_appid.seed_no + "&sales_agent=" + _URL_SALES_AGENT + "&mode=" + mini_mode + "&appid=" + _URL_APPID
    //20260212-6236二维码生成
    $("#qrcode").empty().hide();
    var widthq = $(document ).width() / 2.5;
    var qrcode = new QRCode(document.getElementById("qrcode"), {
        width: widthq,
        height: widthq,
        correctLevel: QRCode.CorrectLevel.L
    });
    qrcode.makeCode(link);
        // 隐藏原始二维码图片
        $("#qrcode img").hide();
        // 获取原始canvas
        var originalCanvas = document.getElementById('qrcode').getElementsByTagName('canvas')[0];
        if (!originalCanvas) {
            console.error("未找到原始二维码canvas");
            return;
        }
        // 创建最终canvas
        var newCanvas = document.createElement('canvas');
        newCanvas.width = widthq;
        newCanvas.height = widthq;
        // 获取上下文
        var ctx = newCanvas.getContext('2d', { willReadFrequently: true });
        // 绘制白色背景
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, newCanvas.width, newCanvas.height);
        // 将原始二维码绘制到新canvas
        ctx.drawImage(originalCanvas, 0, 0, widthq, widthq);
        // 加载并绘制logo
        var img = new Image();
        img.src = "../../images/ruilogo.png";
        img.onload = function() {
            // 绘制logo
            var logoWidth = 40;
            var logoHeight = 25;
            var logoX = (widthq - logoWidth) / 2;
            var logoY = (widthq - logoHeight) / 2;
            // 重新获取上下文以确保状态正确
            ctx = newCanvas.getContext('2d');
            ctx.drawImage(img, logoX, logoY, logoWidth, logoHeight);
            // 转换为图片
            var newCanvasDataURL = newCanvas.toDataURL("image/png", 1.0);
            // 先设置容器样式
            $(".outputline").css({
                'min-height': widthq + 'px',
                'display': 'flex',
                'justify-content': 'center',
                'align-items': 'center',
            });
            // 显示二维码图片
            $("#qrcodeimg").css({
                'max-width': '100%',
                'max-height': widthq + 'px',
                'height': 'auto',
                'width': 'auto',
                'margin': '0 auto',
                'display': 'block'
            });
            // 设置图片源
            $("#qrcodeimg").attr("src", newCanvasDataURL);
            if(!isWeixin) {
                $(".qr_suspend").show();
                $("#qrcode").show();
            }
            
        };
    //二维码兼容性问题修改
    var btn = document.getElementsByClassName("btn")[0];
    var clipboard = new ClipboardJS(btn);
    $(".btn").attr("data-clipboard-text", link);
    $(".copy-links").hide();
    clipboard.on('success', function (e) {
        hxui.toast("链接复制成功");
    });
    clipboard.on('error', function (e) {
        hxui.toast("链接复制失败");
    });
    $.ajax({
        type: 'POST',
        url: commonurl + 'plan/saveseed',
        data: JSON.stringify(aaa),
        timeout: 30000,
        dataType: 'json',
        contentType: "application/json",
        success: function (req) {
            // 二维码
            ewmAjax()
            //mini半自助小程序分享
            var recalljump = function () {
                // 会客厅
                loShare();
                $('#loadingToast').hide();
                if (iswxxcx) {
                    var share_url;
                    var str = "";
                    if (link.indexOf("?") != -1) {
                        share_url = link.split("?")[1];
                    }
                    var path = encodeURIComponent(commonurl_front + "xcxshare.html?" + share_url + "&xcx_page=2")
                    wx.miniProgram.navigateTo({
                        url: '/pages/comshare/comshare?url=' + path
                    })
                    return;
                }
            }
            Recall.recallEnd(return_appid.seed_no, recalljump)
        },
        complete: function (XMLHttpRequest, status) {
            if (status == 'timeout') {
                $('#loadingToast').hide();
                $("#errInfo").show();
            }
        },
        error: function (xhr, type) {
            hxui.toast("网络请求出错");
            $('#loadingToast').hide();
        }
    });
}
//20260212-6236二维码生成-将整个erwm区域绘制成图片并覆盖在原始位置
function replaceEwm() {
    window.scrollTo(0, 0);
    // 先检查元素是否存在
    var erwmElement = document.querySelector('.erwm');
    // 如果元素不存在,直接返回
    if (!erwmElement) {
        console.warn('erwm元素不存在');
        return;
    }
    // 如果元素存在但不可见,设置延迟重试
    if (erwmElement.offsetWidth === 0 || erwmElement.offsetHeight === 0) {
        console.warn('erwm元素不可见,延迟重试...');
    }
    console.log('erwm元素开始处理', erwmElement);
    html2canvas(erwmElement, {
        backgroundColor: '#ffffff',
        scale: 1,
        useCORS: true,  // 启用跨域支持
        allowTaint: false,  // 允许渲染跨域图片
        logging: true,  // 启用日志
        width: erwmElement.offsetWidth,
        height: erwmElement.offsetHeight,
        scrollX: 0,
        scrollY: 0,
        x: 0,
        y: 0,
        onclone: (clonedDoc) => {
            const clonedElement = clonedDoc.querySelector('.erwm');
            clonedElement.style.visibility = 'visible'; // 确保克隆元素可见
        }
    }).then(function(canvas) {
        // 检查元素是否仍然可见
        if (erwmElement.offsetWidth === 0 || erwmElement.offsetHeight === 0) {
            console.warn('元素在处理过程中变为不可见');
        }
        // 创建新的Canvas,只裁剪高度
        var newCanvas = document.createElement('canvas');
        var ctx = newCanvas.getContext('2d', { willReadFrequently: true });
        newCanvas.width = canvas.width;
        newCanvas.height = canvas.height;
        // 从原Canvas裁剪
        ctx.drawImage(
            canvas, 
            0, 0,                    // 源x,y(从左上角开始)
            canvas.width,            // 源宽度(保持原宽度)
            canvas.height,           // 源高度
            0, 0,                    // 目标x,y
            newCanvas.width,         // 目标宽度
            newCanvas.height         // 目标高度
        );
        var erwmImageDataURL = newCanvas.toDataURL("image/png");
            var img = new Image();
            img.src = erwmImageDataURL;
            img.style.cssText = 'width: 100%; height: auto;';
            erwmElement.style.display = 'none';
            erwmElement.parentNode.insertBefore(img, erwmElement);
    }).catch(function(error) {
        console.error('html2canvas转换失败:', error);
        delete erwmElement.dataset.processed;
    });
}
function ewmAjax() {
    var ewmdata={
        "seed_no": hxcjs.getUrlString("seed_no")||return_appid.seed_no,
        "plan_no": "",
        "sales_agent":  _URL_SALES_AGENT,
    }
    $.ajax({
        type: 'POST',
        url: commonurl + 'qrcode/tip/query',
        data: JSON.stringify(ewmdata),
        timeout: 30000,
        dataType: 'json',
        contentType: "application/json",
        success: function (req) {
            $('#loadingToast').hide();
            $(".ewm_amount").text(req.risks[0].amount_insured);
            $(".ewm_premium").text(req.premium);
            $(".ewm_pname").text(req.risks[0].risk_short_name);
            var paymentPeriodValue = req.risks[0].payment_period_value;
            var paymentPeriodText = "";
            if (paymentPeriodValue === "1") {
                paymentPeriodText = "一次交清";
            } else if (paymentPeriodValue) {
                paymentPeriodText = paymentPeriodValue + "年";
            }
            $(".ewm_num").text(paymentPeriodText);
            // 获取.ewm_add容器
            var $ewmAddContainer = $(".ewm_add");
            if ($ewmAddContainer.length > 0) {
                // 清空.ewm_addxing内部的所有内容
                $ewmAddContainer.find('.ewm_addxing').remove();
                if (req.risks && req.risks.length > 0) {
                    $.each(req.risks, function(index, riskItem) {
                        // 忽略第一个元素(索引0),从第二个元素(索引1)开始
                        if (index > 0) {
                            var html = '<div class="ewm_addxing">' +
                                            '<div class="ewm_addcalc"></div>' +
                                            '<p class="ewm_addcalc_name">' + riskItem.risk_short_name + '</p>' +
                                        '</div>';
                                        // 将.ewm_addxing插入到.ewm_add容器内
                                        $ewmAddContainer.append(html);
                        }
                    });
                }
                // 控制显示/隐藏
                if (req.risks && req.risks.length == 1) {
                    $(".ewm_add").hide();
                } else {
                    $(".ewm_add").show();
                }
            }
            setTimeout(function() {
                replaceEwm();
            }, 1000);
        },
        complete: function (XMLHttpRequest, status) {
            if (status == 'timeout') {
                $('#loadingToast').hide();
                $("#errInfo").show();
            }
        },
        error: function (xhr, type) {
            hxui.toast("网络请求出错");
            $('#loadingToast').hide();
        }
    });
}
  • 写回答

1条回答 默认 最新

  • 檀越@新空间 2026-03-26 11:23
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 html2canvas 进行屏幕截图时,如果截图内容显示为空白,通常是由以下几个常见原因引起的。以下是一个详细的解决方案,并附有代码修改建议


    一、问题分析

    你提到的“弹框样式内容先显示了,然后过了一秒变成空白的img”,这表明:

    • 页面元素在初始渲染时是可见的。
    • 然后通过某些逻辑(如生成二维码)导致内容被替换或隐藏。
    • html2canvas 在执行时,可能没有等到内容完全渲染完成,就进行了截图,因此出现空白。

    二、解决步骤

    1. 确保 DOM 元素已完全加载

    html2canvas 需要等待页面元素完全加载后才能正确捕获内容。可以使用 window.onloadDOMContentLoaded 事件来确保这一点。

    window.addEventListener('load', function () {
        // 执行 html2canvas 的代码
    });
    

    2. 等待异步操作完成后再进行截图

    如果你在生成二维码等操作中使用了异步函数(如 qrcode.makeCode(link)),需要等待这些操作完成后,再调用 html2canvas

    修改前的代码片段:

    function savePlan() {
        link = ...;
        qrcode.makeCode(link); // 异步操作
        html2canvas(...);
    }
    

    修改后的代码片段:

    function savePlan() {
        link = ...;
    
        // 使用 Promise 包装二维码生成
        return new Promise((resolve) => {
            var qrcode = new QRCode(document.getElementById("qrcode"), {
                width: widthq,
                height: widthq,
                correctLevel: QRCode.CorrectLevel.L
            });
            qrcode.makeCode(link);
    
            // 假设二维码生成后触发一个事件或回调
            setTimeout(() => {
                resolve();
            }, 1000); // 假设生成需要1秒
        }).then(() => {
            html2canvas(document.querySelector("#mask")).then(canvas => {
                // 处理 canvas
            });
        });
    }
    

    ⚠️ 如果你使用的 QRCode.js 支持回调函数,请直接在 makeCode() 中使用回调,而不是 setTimeout


    3. 检查 html2canvas 的配置

    确保 html2canvas 正确地将目标元素作为参数传入,并且该元素在 DOM 中存在。

    html2canvas(document.querySelector("#mask")).then(canvas => {
        document.body.appendChild(canvas);
    });
    

    4. 检查 CSS 样式是否影响截图

    某些 CSS 属性(如 visibility: hiddendisplay: noneopacity: 0)会导致 html2canvas 忽略元素内容。请确保目标元素在截图时是可见的。

    重点注意:

    • visibility: visible 不等于 display: block
    • 你当前的 .ewm 类设置了 visibility: visible; position: static;,但可能被其他样式覆盖。
    • 检查是否有动态样式(如 JS 设置的 display: none)在截图时生效。

    5. 检查跨域资源问题

    如果你的页面中引用了外部图片(如 background-image<img> 标签),可能会因为跨域问题导致 html2canvas 无法正确绘制内容。

    解决方案:

    • 确保所有图片都来自同一域名。
    • 使用 crossOrigin: 'anonymous' 选项(适用于支持 CORS 的图片)。
    html2canvas(document.querySelector("#mask"), {
        useCORS: true
    }).then(canvas => {
        // ...
    });
    

    三、完整修改示例

    以下是根据你提供的代码片段,优化后的 savePlan 函数:

    function savePlan() {
        let link = commonurl_front + "&seed_no=" + return_appid.seed_no + 
                   "&sales_agent=" + _URL_SALES_AGENT + "&mode=" + mini_mode + 
                   "&appid=" + _URL_APPID;
    
        // 创建二维码
        const qrcodeContainer = document.getElementById("qrcode");
        const widthq = window.innerWidth / 2.5;
    
        // 清空旧二维码
        qrcodeContainer.innerHTML = '';
        
        // 生成新二维码
        const qrcode = new QRCode(qrcodeContainer, {
            width: widthq,
            height: widthq,
            correctLevel: QRCode.CorrectLevel.L
        });
    
        // 等待二维码生成完成
        qrcode.makeCode(link);
    
        // 等待一段时间确保生成完成
        setTimeout(() => {
            html2canvas(document.querySelector("#mask"), {
                useCORS: true
            }).then(canvas => {
                // 将截图添加到页面或下载
                document.body.appendChild(canvas);
                // 或者导出为图片
                const imgData = canvas.toDataURL("image/png");
                const link = document.createElement("a");
                link.href = imgData;
                link.download = "screenshot.png";
                link.click();
            });
        }, 1000); // 假设生成需要1秒
    }
    

    四、总结

    | 问题原因 | 解决方案 | |---------|----------| | 页面未完全加载 | 使用 window.onloadDOMContentLoaded | | 异步操作未完成 | 使用 PromisesetTimeout 等待生成完成 | | CSS 样式影响 | 检查 displayvisibilityopacity 等属性 | | 跨域资源问题 | 使用 useCORS: true 或确保资源同源 |


    如果你能提供完整的 HTML 和 JavaScript 代码,我可以进一步帮你定位具体问题。希望以上内容对你有帮助!

    评论

报告相同问题?

问题事件

  • 创建了问题 3月26日