简体   繁体   English

如何将 Leaflet map 的 dom-to-image 捕获与地图边界对齐?

[英]How to align dom-to-image capture of Leaflet map to map's bounds?

I'm working on a project in which i'm capturing map screenshot (using dom-to-image library ) and sending it to an external API which is returning back some coordinates(x,y,w,h) after processing the sent image.我正在做一个项目,在该项目中我正在捕获 map 屏幕截图(使用dom-to-image 库)并将其发送到外部 API 处理发送后返回一些坐标(x,y,w,h)图片。 These co-ordinates(rectangles) i'm trying to draw on leaflet.我试图在 leaflet 上绘制这些坐标(矩形)。

As the captured image size is bigger than width and height of captured area (don't know why) , I need to do scaling the co-ordinates.由于捕获的图像尺寸大于捕获区域的宽度和高度(不知道为什么) ,我需要缩放坐标。

Now the problem is Leaflet rectangles are not drawing on accurate position which external API is returning.现在的问题是 Leaflet 矩形没有绘制在外部 API 正在返回的准确 position 上。

However, I'm sure that the external API is returning correct coordinates(x,y,w,h) with respect to sent image's width & height.但是,我确信外部 API 正在返回关于发送图像宽度和高度的正确坐标(x,y,w,h)。

Something wrong i'm doing on scaling coordinates.我在缩放坐标上做错了什么。

Below is the code snippet i'm trying:下面是我正在尝试的代码片段:

domtoimage.toPng(document.querySelector("#map"))
    .then(function (dataUrl) {
        var boundsOnly = map.getBounds(); 
        let topLeft = boundsOnly.getNorthWest();
        let topRight = boundsOnly.getNorthEast();
        let bottomLeft = boundsOnly.getSouthWest();
        let bottomRight = boundsOnly.getSouthEast();
                
        var currBBOXpoints = { x1y1: map.latLngToLayerPoint(topLeft), 
                            x2y2: map.latLngToLayerPoint(topRight),
                            x3y3: map.latLngToLayerPoint(bottomRight),
                            x4y4: map.latLngToLayerPoint(bottomLeft) };
                            
        var pW = currBBOXpoints.x2y2.x - currBBOXpoints.x1y1.x;
        var pH = currBBOXpoints.x3y3.y - currBBOXpoints.x1y1.y;
        
        currBBOXpoints.pW = pW; //calculated the width of captured area
        currBBOXpoints.pH = pH; //calculated the height of captured area
        
        var i = new Image();
        i.onload = function () { //calculating captured image's actual width, height

            $.ajax({
                type: 'post',
                url: '/externalapi',
                data: JSON.stringify(dataUrl),
                contentType: "application/json",
                dataType: "json",
                success: function (resultData) {
                    resultData["iW"] = i.width; //captured image width 
                    resultData["iH"] = i.height; //captured image height
                    resultData["currBBOXpoints"] = currBBOXpoints; //captured area bounds
                    drawRects(resultData);
                    //NOTE: Captured image's width and height are bigger than width and height of captured area (don't know why)
                }
            });
    };
    i.src = dataUrl;
});

function drawRects(rectData) {

    var scale = Math.max(rectData.currBBOXpoints.pW / rectData['iW'], rectData.currBBOXpoints.pH / rectData['iH']);
    
    var shifted_x = rectData.currBBOXpoints.pW / 2 - rectData['iW'] / 2 * scale;
    var shifted_y = rectData.currBBOXpoints.pH / 2 - rectData['iH'] / 2 * scale;

    rectData.od.forEach(rc => {
        var modifiedX = Number(rc['x']) * scale + shifted_x;
        var modifiedY = Number(rc['y']) * scale + shifted_y; 
        var modifiedW = (modifiedX + rc['w'])
        var modifiedH = (modifiedY + rc['h'])


        let point3 = map.layerPointToLatLng(L.point(modifiedX, modifiedY));
        let point4 = map.layerPointToLatLng(L.point(modifiedW, modifiedH));
        
        var rectBounds = [[point3.lat, point3.lng], [point4.lat, point4.lng]];
        var boundingBox = L.rectangle(rectBounds, { color: "yellow", weight: 1, name: "rect", fillOpacity: 0.10 });
        
        map.addLayer(boundingBox);

    });
}

I can't say why but when you set the scale to 0.9 after defining x and y it matches perfect.我不能说为什么,但是当您在定义xy后将比例设置为 0.9 时,它匹配完美。

var scale = Math.max(currBBOXpoints.pW / imagesize.width, currBBOXpoints.pH / imagesize.height);

var x = currBBOXpoints.pW / 2 - imagesize.width / 2 * scale;
var y = currBBOXpoints.pH / 2 - imagesize.height / 2 * scale;
scale = 0.9

Also you have to set in the fiddle the css width and height:您还必须在小提琴中设置 css 宽度和高度:

#mapWrapper{
  padding: 10px;
  margin: 10px;
  width: 1744px;
  height: 854px;
}

This is an XY problem (which you successfully identified: the size of the capture is not the size of the map container), so let's fix the root problem instead.这是一个XY 问题(您已成功识别:捕获的大小不是 map 容器的大小),所以让我们改为修复根本问题。

It looks like dom-to-image aligns the top-left corner of the capture, but also takes into account the size of any overflowing elements (such as partially-visible map tiles on the southeast corner) when calculating the size of the capture:看起来dom-to-image对齐了捕获的左上角,但在计算捕获的大小时还考虑了任何溢出元素的大小(例如东南角的部分可见 map 瓦片):

捕获比较

(This can be proven by playing a bit with the browser's box model inspector , comparing the position & size of the southeasternmost tile with the size of the capture) (这可以通过使用浏览器的盒子 model 检查器来证明,比较 position 和最东南方瓦片的大小与捕获的大小)

Since the capture is aligned top-left, you can just clip the capture to the size of the map canvas.由于捕获对齐左上角,您可以将捕获剪辑到 map canvas 的大小。

You can use the width and height options of dom-to-image together with the getSize method of L.Map to force clipping the captured image to the dimensions of the map canvas, eg:您可以使用dom-to-imagewidthheight选项以及L.MapgetSize方法来强制将捕获的图像裁剪为 map canvas 的尺寸,例如:

    domtoimage.toPng(document.querySelector("#leaflet"), {
        width: map.getSize().x,
        height: map.getSize().y
    })

See a working demo .查看工作演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM