如何使用带有坐标的html2canvas?

How to use html2canvas with coordinates?

我正在尝试使用 html2canvas. Capturing an image of the whole browser works. But I need to specify x,y start and end coordinates that I want to capture. In the docs 在浏览器中捕获图像 我看到 html2canvas 可以接受 x,y 坐标:

x: Default: Element x-offset Description: Crop canvas x-coordinate
y: Default: Element y-offset Description: Crop canvas y-coordinate

将我的 x,y 坐标传递给那些参数只会捕获整个 window。

因此,我尝试捕获整个 window,然后使用 drawImage() 从中裁剪一个区域(在其他一些 Whosebug post 中找到,而不是确定哪个):

function snapImage(x1,y1,x2,y2, e){
    html2canvas(document.body).then(function(canvas) {
        // calc the size -- but no larger than the html2canvas size!
        var width = Math.min(canvas.width,Math.abs(x2-x1));
        var height = Math.min(canvas.height,Math.abs(y2-y1));
        // create a new avatarCanvas with the specified size
        var avatarCanvas = document.createElement('canvas');
        avatarCanvas.width=width;
        avatarCanvas.height=height;
        avatarCanvas.id = 'avatarCanvas';
        // put avatarCanvas into document body
        document.body.appendChild(avatarCanvas);
        // use the clipping version of drawImage to draw
        // a clipped portion of html2canvas's canvas onto avatarCanvas
        var avatarCtx = avatarCanvas.getContext('2d');
        avatarCtx.drawImage(canvas,x1,y1,width,height,0,0,width,height);
    });
}

这会绘制偏移量错误的移位图像。例如,给定以下网站:

图片取自示例:https://github.com/niklasvh/html2canvas/tree/master/examples

我标记“pluot?”区域来抓拍它:

查看虚线矩形

虚线矩形是使用js绘制的,在2个事件中给定鼠标坐标:onmousedownonmouseup。因为矩形绘制正确,我假设我的坐标是正确的。但是当我将这些坐标传递给上面的函数 snapImage() 时,我得到以下捕获的图像:

看起来有偏差。也许开始坐标 drawImage() 与我的 canvas 开始坐标不同?


编辑:

事实证明,我的代码在 100% 缩放时有效。但是当我放大/缩小时却没有。

我想这是因为你从事件中得到了 x 和 y 和 clientX 和 clientY。请改用 pageX 和 pageY。看看这个 jsFiddle

let startX, startY;

document.getElementsByTagName('body')[0].addEventListener('mousedown', function(event) {
    console.log("ok");
    startX = Math.floor(event.pageX);
    startY = Math.floor(event.pageY);
});

document.getElementsByTagName('body')[0].addEventListener('mouseup', function(event) {
    snapImage(Math.min(event.pageX, startX), Math.min(event.pageY, startY), Math.max(event.pageX, startX), Math.max(event.pageY, startY));
});

function snapImage(x1,y1,x2,y2, e){
    console.log(x1, x2, y1, y2);
    html2canvas(document.body).then(function(canvas) {
        // calc the size -- but no larger than the html2canvas size!
        var width = Math.min(canvas.width,Math.abs(x2-x1));
        var height = Math.min(canvas.height,Math.abs(y2-y1));
        // create a new avatarCanvas with the specified size
        var avatarCanvas = document.createElement('canvas');
        avatarCanvas.width=width;
        avatarCanvas.height=height;
        avatarCanvas.id = 'avatarCanvas';
        // put avatarCanvas into document body
        document.body.appendChild(avatarCanvas);
        // use the clipping version of drawImage to draw
        // a clipped portion of html2canvas's canvas onto avatarCanvas
        var avatarCtx = avatarCanvas.getContext('2d');
        avatarCtx.drawImage(canvas,x1,y1,width,height,0,0,width,height);
    });
}

原来有一个 built-in chrome 函数 captureVisibleTab that captures the image of the active tab. So I ended up using that instead of html2canvas. I got help from the Copyfish Chrome Extension. Github code here: Copyfish.

这是我的代码:

听众:

//listener in background.js which invokes the screen capture
chrome.tabs.captureVisibleTab(function (dataURL) {
    sendResponse({
            dataURL: dataURL,
    });
});

接收者:

//receiver in content.js which gets the captured image and crops it accordingly
function(response){
    var img = new Image();
    img.src = response.dataURL;
    var dpf = window.innerWidth / img.width;
    var scaleFactor = 1 / dpf,
    sx = Math.min(x1, x2) * scaleFactor,
    sy = Math.min(y1, y2) * scaleFactor,
    width = Math.abs(x2 - x1),
    height = Math.abs(y2 - y1);

    // create a new avatarCanvas with the specified size
    var avatarCanvas = document.createElement('canvas');
    avatarCanvas.width = width;
    avatarCanvas.height = height;
    avatarCanvas.id = 'avatarCanvas';
    // put avatarCanvas into document body
    document.body.appendChild(avatarCanvas);
    // use the clipping version of drawImage to draw
    var avatarCtx = avatarCanvas.getContext('2d');
    avatarCtx.drawImage(img, sx, sy, scaledWidth, scaledHeight, 0, 0, width, height);
}

x,y坐标分别由e.clientXe.clientY

此方法不受缩放和分辨率限制。