onclone(html2canvas)期间应用更改后屏幕截图的垂直裁剪

问题描述 投票:0回答:2

html2canvas
非常适合截取屏幕截图,但目前无法在 textAreas 中捕获较长的文本或在多选中捕获多个变量。参见 https://github.com/niklasvh/html2canvas/issues/2008 进行讨论。

@chawes13 提供了很好的建议来解决这些导致以下功能的问题。我设置

height: document.body.scrollHeight
垂直裁剪我正在处理的应用程序的屏幕截图。但是,高度可以在
onclone
过程中改变。我尝试了很多不同的选择,但似乎唯一可行的是(1)不使用任何垂直裁剪或(2)使用基于初始身高的裁剪,不幸的是,它切断了下半部分如果在
onclone
期间进行了更改,则图像。该应用程序有很多选项卡,并且会随着加载不同的数据或选择变量而动态更改大小,因此无法设置为一个固定高度。

问题:是否可以确定克隆文档的(滚动)高度,并在需要时使用它来调整屏幕截图高度?

function generate_screenshot() {
  html2canvas($("body")[0], {
    y: 55,
    height: document.body.scrollHeight,
    onclone: (clonedDocument) => {
      Array.from(clonedDocument.querySelectorAll("textarea")).forEach((textArea) => {
        if (textArea && textArea.value.length > 30) {
          const labelFor = textArea.getAttribute("id")
          const label = clonedDocument.querySelector(`label[for="${labelFor}"]`)
          const div = clonedDocument.createElement("div")
          div.innerText = textArea.value
          div.style.border = "1px solid #d3d3d3"
          div.style.padding = "10px 10px 10px 10px"
          div.style.width = "100%"
          div.style.borderRadius = "5px"
          div.style.boxSizing = "border-box";
          div.style.margin = "0";
          div.style.backgroundColor = "white"
          textArea.style.display = "none"
          textArea.parentElement.append(label, div);
        }
      })

      Array.from(clonedDocument.querySelectorAll('select[multiple]')).forEach((msel) => {
        const multiSelect = document.querySelector("#" + msel.getAttribute("id"));
        if (multiSelect && multiSelect.selectedOptions.length > 1) {
          const clonedMultiSelect = clonedDocument.querySelector("#" + msel.getAttribute("id"));
          const list = clonedDocument.createElement('ul')
          Array.from(multiSelect.selectedOptions).forEach((option) => {
            const item = clonedDocument.createElement('li')
            item.innerHTML = option.value
            item.style = "list-style: none; padding-left: 0.5em"
            item.style.width = "100%"
            list.appendChild(item)
          })
          list.style.border = "1px solid #d3d3d3"
          list.style.padding = "5px 5px 5px 5px"
          list.style.width = "100%"
          list.style.backgroundColor = "white"
          list.style.borderRadius = "5px"
          clonedMultiSelect.style.display = "none"
          clonedMultiSelect.parentElement.appendChild(list)
        }
      });
    },
    ignoreElements: function(el) {
      return el.classList.contains("navbar-inverse") || el.classList.contains("dropdown-menu");
    }
  }).then(canvas => {
    var img = document.createElement("img");
    img.src = canvas.toDataURL("png");
    img.width = parseInt(canvas.style.width);
    img.height = parseInt(canvas.style.height);
    $("#screenshot_preview").empty();
    $("#screenshot_preview").append(img);
  });
}
javascript html html2canvas
2个回答
0
投票

好的,没有测试过,但你可以尝试这样的事情:

function generate_screenshot() {
  html2canvas($("body")[0], {
    y: 55,
    onclone: (clonedDocument) => {
      Array.from(clonedDocument.querySelectorAll("textarea")).forEach((textArea) => {
        if (textArea && textArea.value.length > 30) {
          const labelFor = textArea.getAttribute("id")
          const label = clonedDocument.querySelector(`label[for="${labelFor}"]`)
          const div = clonedDocument.createElement("div")
          div.innerText = textArea.value
          div.style.border = "1px solid #d3d3d3"
          div.style.padding = "10px 10px 10px 10px"
          div.style.width = "100%"
          div.style.borderRadius = "5px"
          div.style.boxSizing = "border-box";
          div.style.margin = "0";
          div.style.backgroundColor = "white"
          textArea.style.display = "none"
          textArea.parentElement.append(label, div);
        }
      })

      Array.from(clonedDocument.querySelectorAll('select[multiple]')).forEach((msel) => {
        const multiSelect = document.querySelector("#" + msel.getAttribute("id"));
        if (multiSelect && multiSelect.selectedOptions.length > 1) {
          const clonedMultiSelect = clonedDocument.querySelector("#" + msel.getAttribute("id"));
          const list = clonedDocument.createElement('ul')
          Array.from(multiSelect.selectedOptions).forEach((option) => {
            const item = clonedDocument.createElement('li')
            item.innerHTML = option.value
            item.style = "list-style: none; padding-left: 0.5em"
            item.style.width = "100%"
            list.appendChild(item)
          })
          list.style.border = "1px solid #d3d3d3"
          list.style.padding = "5px 5px 5px 5px"
          list.style.width = "100%"
          list.style.backgroundColor = "white"
          list.style.borderRadius = "5px"
          clonedMultiSelect.style.display = "none"
          clonedMultiSelect.parentElement.appendChild(list)
        }
      });

      // Dynamically adjust height based on cloned document's scroll height
      var clonedBody = clonedDocument.querySelector("body");
      var clonedHeight = clonedBody.scrollHeight;
      clonedBody.style.height = clonedHeight + "px";
    },
    ignoreElements: function(el) {
      return el.classList.contains("navbar-inverse") || el.classList.contains("dropdown-menu");
    }
  }).then(canvas => {
    var img = document.createElement("img");
    img.src = canvas.toDataURL("png");
    img.width = parseInt(canvas.style.width);
    img.height = parseInt(canvas.style.height);
    // Dynamically adjust width and height based on cloned document's size
    var clonedBody = canvas.parentNode.querySelector("body");
    var clonedWidth = clonedBody.offsetWidth;
    var clonedHeight = clonedBody.offsetHeight;
    canvas.style.width = clonedWidth + "px";
    canvas.style.height = clonedHeight + "px";
    $("#screenshot_preview").empty();
    $("#screenshot_preview").append(img);
  });
}

基本上我将“onclone”移到了开头,在高度和 y 选项之前。在 onclone 函数中,我添加了代码以根据克隆文档的滚动高度动态调整高度。


0
投票

我曾经在尝试从报告页面创建 PDF 时遇到过这个问题。这是我的代码。它不仅在拆分页面时打印所有内容。

splitImages(canvas: HTMLCanvasElement, maxHeight: number) {
    let y = 0;
    let images = [];
    let acanvas = [];
    let ctx = canvas.getContext('2d');
    while (y < canvas.height) {
        let height = y + maxHeight > canvas.height ? canvas.height - y : y + maxHeight;
        let imgData = ctx.getImageData(0, y, canvas.width, y + height);
        let newCanvas = document.createElement('canvas');
        newCanvas.width = canvas.width;
        newCanvas.height = maxHeight;
        let ctxNewCanvas = newCanvas.getContext('2d');
        ctxNewCanvas.putImageData(imgData, 0, 0);
        if (y + maxHeight < canvas.height)
            this.trimCanvas(newCanvas);
        acanvas.push(newCanvas);
        images.push(newCanvas.toDataURL());
        y = y + newCanvas.height;
    }
    return { images, acanvas };
}

exportPDF(div_id: string, relName: string, mode: string = 'table', trimCanvas: boolean = true) {
    let data: HTMLElement = document.getElementById(div_id);
    html2canvas(data, {
        windowHeight: data.scrollHeight,
        scrollY: -window.scrollY,
        onclone: doc => {
            doc.querySelector('#' + div_id).removeChild(doc.querySelector("#btnExport"));
            (<HTMLElement>doc.querySelector('#relLogo span')).style.display = 'flex';
            if (mode == 'table') {
                let tr = document.createElement('tr');
                let numCols = doc.querySelector('tbody tr').children.length;
                tr.innerHTML = "<td colspan='" + numCols + "'></td>";
                doc.querySelector('tbody').lastChild.after(tr);
            }
        }
    }).then(canvas => {
        let pdf: jsPDF = new jsPDF({ orientation: 'landscape', unit: 'px', format: 'a4' });
        if (trimCanvas)
            this.trimCanvas(canvas);
        const dataUrl: string = canvas.toDataURL()

        const imgProps: ImageProperties = pdf.getImageProperties(dataUrl);
        let pdfWidth: number = pdf.internal.pageSize.getWidth() * 0.95;
        let pdfHeight: number = pdf.internal.pageSize.getHeight() * 0.925;
        let borderTop: number = pdf.internal.pageSize.getWidth() * 0.025;
        let borderLeft: number = pdf.internal.pageSize.getHeight() * 0.025;
        let maxPxPP = (pdfHeight / pdfWidth) * imgProps.width;
        let canvasSection = this.splitImages(canvas, maxPxPP);
        let imagens: string[] = canvasSection.images;

        pdf.addImage(imagens[0], 'PNG', borderLeft, borderTop, pdfWidth, pdfHeight);
        if (imagens.length > 1) {
            imagens.shift();
            imagens.forEach(img => {
                pdf.addPage('a4', 'l');
                pdf.addImage(img, 'PNG', borderLeft, borderTop, pdfWidth, pdfHeight);
            })
        }
        pdf.save(relName + '.pdf');
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.