You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript截取div/canvas区域可见内容的屏幕截图

问题根因

你当前代码导出空白截图是三个核心错误导致的:

  • 逻辑自引用错误:takeScreenshot函数中你对刚创建的透明空canvas执行drawImage(canvas自身, 0,0),相当于把空白内容画到空白画布上,自然得不到有效内容。
  • 原生API能力限制:Canvas 2D的drawImage方法仅支持图片、其他canvas、视频这类已经光栅化的源,不能直接绘制普通DOM节点,没有办法靠原生浏览器API直接把div区域的页面内容画到canvas上。
  • Canvas分辨率配置错误:你只给canvas设置了CSS样式宽高,没有设置标签原生的width和height属性,canvas实际渲染分辨率是默认的300px*150px,和显示尺寸不匹配,就算有内容也会出现拉伸、模糊问题。
  • 附带样式bug:原代码中box-sizing属性拼写错误(多了空格)、截图按钮没有设置底部定位会遮挡画布区域,也会影响截图区域的准确性。
修复后可直接运行代码

以下代码可以直接粘贴到浏览器控制台执行,实现选框区域截图+表单弹出的完整逻辑:

// 动态加载DOM转Canvas依赖
function loadScript(url, callback) {
    const script = document.createElement('script');
    script.src = url;
    script.onload = callback;
    document.head.appendChild(script);
}

Start();
function Start() {
    var button = document.createElement("button");
    button.setAttribute("id", "mainBtn");
    button.innerHTML = "+";
    button.style.cursor = "pointer";
    button.style.textTransform = "uppercase";
    button.style.position = "absolute";
    button.style.top = "50px";
    button.style.left = "100px";
    document.getElementsByTagName("body")[0].appendChild(button);
    button.addEventListener('click', CreateBox);
}

function CreateBox() {
    var button = document.getElementById("mainBtn");
    button.style.display = "none";
    var mainBox = document.createElement("div");
    mainBox.setAttribute("id", "mainBox");
    mainBox.style.position = "absolute";
    mainBox.style.top = "50px";
    mainBox.style.left = "130px";
    mainBox.style.width = "400px";
    mainBox.style.height = "400px";
    mainBox.style.boxSizing = "border-box";
    mainBox.style.zIndex = "99";
    mainBox.style.display = "block";
    mainBox.style.border = "10px solid rgb(222, 221, 221)";
    var cover = document.createElement("div");
    cover.setAttribute("id", "cover");
    cover.style.position = "relative";
    cover.style.width = "100%";
    cover.style.height = "100%";
    mainBox.appendChild(cover);

    var capture = document.createElement("canvas");
    capture.setAttribute("id", "capture");
    // 配置canvas实际渲染分辨率,和显示尺寸匹配
    capture.width = 380;
    capture.height = 340;
    capture.style.width = "100%";
    capture.style.height = "calc(400px - 50px)";
    capture.style.display = "block";
    capture.style.backgroundColor = "transparent";
    cover.appendChild(capture);

    var captureBtn = document.createElement("button");
    captureBtn.setAttribute("id", "capture-btn");
    captureBtn.innerHTML = 'Click to enquiry';
    captureBtn.style.backgroundColor = "rgb(222, 221, 221)";
    captureBtn.style.border = "none";
    captureBtn.style.width = "calc(100% + 20px)";
    captureBtn.style.height = "50px";
    captureBtn.style.fontWeight = "600";
    captureBtn.style.fontSize = "25px";
    captureBtn.style.position = "absolute";
    captureBtn.style.left = "-10px";
    captureBtn.style.bottom = "-10px";
    captureBtn.style.cursor = "pointer";
    captureBtn.addEventListener('click', takeScreenshot);
    cover.appendChild(captureBtn);

    document.getElementsByTagName("body")[0].appendChild(mainBox);
}

function takeScreenshot() {
    const box = document.getElementById('mainBox');
    // 获取选框实际位置,计算需要截图的内部区域(排除边框和按钮)
    const boxRect = box.getBoundingClientRect();
    const captureArea = {
        x: boxRect.left + 10,
        y: boxRect.top + 10,
        width: boxRect.width - 20,
        height: boxRect.height - 60
    };
    // 先隐藏选框本身,避免把选框、按钮截入结果
    box.style.display = "none";
    // 等待DOM重绘完成后执行截图
    setTimeout(() => {
        html2canvas(document.body, {
            x: captureArea.x,
            y: captureArea.y,
            width: captureArea.width,
            height: captureArea.height,
            useCORS: true,
            scale: window.devicePixelRatio // 适配高DPI屏幕,保证截图清晰度
        }).then(canvas => {
            const dataURL = canvas.toDataURL('image/png');
            CreateForm(dataURL);
        }).catch(err => {
            console.error('截图失败:', err);
            CreateForm('');
        });
    }, 100);
}

function CreateForm(screenshotUrl) {
    var br = document.createElement("br");
    var enquiryForm = document.createElement("div");
    enquiryForm.setAttribute("id", "enquiry-form");
    enquiryForm.style.position = "absolute";
    enquiryForm.style.top = "30px";
    enquiryForm.style.right = "500px";
    enquiryForm.style.width = "400px";
    enquiryForm.style.boxSizing = "border-box";
    enquiryForm.style.zIndex = "99";
    enquiryForm.style.border = "10px solid rgb(222, 221, 221)";
    enquiryForm.style.display = "block";

    var formImage = document.createElement("div");
    formImage.setAttribute("class", "form-image");
    formImage.style.width = "100%";
    formImage.style.height = "350px";
    var image = document.createElement("img");
    image.setAttribute("class", "form-image");
    image.src = screenshotUrl;
    image.style.width = "100%";
    image.style.height = "350px";
    image.style.objectFit = "cover";
    formImage.appendChild(image);

    var form = document.createElement("form");
    form.setAttribute("id", "form-details");
    form.style.backgroundColor = "rgb(222, 221, 221)";
    form.style.color = "black";
    form.style.padding = "10px";
    form.style.fontSize = "15px";
    form.setAttribute("method", "post");

    var FN = document.createElement("input");
    FN.setAttribute("type", "text");
    FN.setAttribute("name", "FullName");
    FN.setAttribute("placeholder", "Full Name");
    FN.style.width = "100%";
    FN.style.height = "32px";
    FN.style.borderRadius = "5px";
    FN.style.border = "none";
    FN.style.padding = "0 8px";
    FN.style.boxSizing = "border-box";

    var DOB = document.createElement("input");
    DOB.setAttribute("type", "text");
    DOB.setAttribute("name", "phone");
    DOB.setAttribute("placeholder", "Phone no.");
    DOB.style.width = "100%";
    DOB.style.height = "32px";
    DOB.style.borderRadius = "5px";
    DOB.style.border = "none";
    DOB.style.padding = "0 8px";
    DOB.style.boxSizing = "border-box";

    var EID = document.createElement("input");
    EID.setAttribute("type", "text");
    EID.setAttribute("name", "emailID");
    EID.setAttribute("placeholder", "E-Mail ID");
    EID.style.width = "100%";
    EID.style.height = "32px";
    EID.style.borderRadius = "5px";
    EID.style.border = "none";
    EID.style.padding = "0 8px";
    EID.style.boxSizing = "border-box";

    var s = document.createElement("button");
    s.innerHTML = "Submit";
    s.style.width = "100%";
    s.style.height = "32px";
    s.style.cursor = "pointer";
    s.style.borderRadius = "5px";
    s.style.border = "none";
    // 输入内容校验,所有字段填完才允许提交
    const checkValid = () => {
        const canSubmit = FN.value.trim() && DOB.value.trim() && EID.value.trim();
        s.style.pointerEvents = canSubmit ? 'auto' : 'none';
        s.style.opacity = canSubmit ? '1' : '0.6';
    };
    FN.addEventListener('input', checkValid);
    DOB.addEventListener('input', checkValid);
    EID.addEventListener('input', checkValid);
    checkValid();

    form.appendChild(FN);
    form.appendChild(br.cloneNode());
    form.appendChild(DOB);
    form.appendChild(br.cloneNode());
    form.appendChild(EID);
    form.appendChild(br.cloneNode());
    form.appendChild(br.cloneNode());
    form.appendChild(s);

    enquiryForm.appendChild(formImage);
    enquiryForm.appendChild(form);
    document.getElementsByTagName("body")[0].appendChild(enquiryForm);
}

// 加载截图依赖
loadScript('https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js', () => {
    console.log('截图模块加载完成');
});
关键改动说明
  • 替换了无效的自绘截图逻辑,通过DOM光栅化能力直接截取指定坐标区域的页面内容,截图前自动隐藏选框,不会把选框边框、操作按钮截入最终结果。
  • 修复了所有样式bug:修正了box-sizing拼写错误、调整了按钮定位、给canvas设置了匹配的渲染分辨率、补全了表单输入框的基础样式避免布局溢出。
  • 增加了适配逻辑:自动适配高DPI屏幕保证截图清晰度,开启跨域图片支持,页面中允许跨域的图片可以正常被截入。
  • 优化了交互体验:表单提交按钮默认禁用,所有输入框填写完成后才允许点击,截图生成后自动填充到表单的图片区域直接展示。

内容的提问来源于stack exchange,提问作者Noob_Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:36:14