无法从画布上制作一块 [英] Unable to make a chunk from canvas
问题描述
我希望与地图进行这种交互,以便当用户选择地图上的某个区域时,就会从该区域创建图像.在此小提琴中,我做了一个最小化和可复制的示例.最重要的部分是此裁剪功能:
I want to have such an interaction with a map, that when a user selects some area on the map, an image is created from this area. I made a minimized and compiltely reproducible example in this fiddle. The most important part is this crop function:
function crop(img, sx, sy, dw, dh) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = dw;
canvas.height = dh;
ctx.drawImage(img, sx, sy, dw, dh, 0, 0, dw, dh);
return canvas.toDataURL("image/png");
}
此功能在所选区域之外创建一个块.这就是选择的样子:
This function creates a chunk out of selected area. This is how selection looks like:
但这就是我得到的结果:
But this is what I get as a result:
所以,我的块完全不正确.但是更有趣的是,在某些任意计算机上和某些任意浏览器中,块是正确的.因此,我确实需要使该代码跨平台和跨浏览器.
So, my chunk is totally incorrect. But what is more interesting is that on some arbitrary computers and in some arbitrary browsers chunks are correct. So, I really need to make this code cross-platform and cross-browser.
推荐答案
但是问题是,从JavaScript代码看来,不可能知道这个系统/浏览器参数-我的意思是初始页面缩放级别.
But the problem is, it seems like from JavaScript code it is impossible to know this system/browser parameter - I mean initial page zoom level.
实际上有 window.devicePixelRatio
只需使用它代替ratio_W
和ratio_H
,它就会开始工作:
Actually there is window.devicePixelRatio
Just use it in place of ratio_W
and ratio_H
, and it starts working:
var initialZoom = devicePixelRatio;
var map = new ol.Map({
layers: [new ol.layer.Tile({
source: new ol.source.OSM()
})],
target: 'map',
view: new ol.View({
center: [-348792.96, 7170957.18],
zoom: 10
})
});
var draw = new ol.interaction.Draw({
features: new ol.Collection(),
type: "LineString",
style: function (feature) {
var style = [
new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(142,142,142,0.5)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(142,142,142,1)',
lineDash: [4,4],
width: 2
})
})
];
return style;
},
geometryFunction: function (coordinates, geom) {
if (!geom) {
geom = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
var mapExtent = map.getView().calculateExtent(map.getSize());
var chunk = [start, [start[0], end[1]], end, [end[0], start[1]],start];
var coords = [[[mapExtent[0],mapExtent[1]],[mapExtent[0],mapExtent[3]],[mapExtent[2],mapExtent[3]],[mapExtent[2],mapExtent[1]],[mapExtent[0],mapExtent[1]]], chunk];
map.exportExtent = coordinates; // all you need
geom.setCoordinates(coords);
return geom;
},
maxPoints: 2
});
var canvas = map.getViewport().firstChild;
draw.on("drawend", function (e) {
var image = new Image(),
link = document.getElementById("export-png");
var topLeft = map.getPixelFromCoordinate(map.exportExtent[0]);
var bottomRight = map.getPixelFromCoordinate(map.exportExtent[1]);
var sx = topLeft[0];
var sy = topLeft[1];
var dw = bottomRight[0] - topLeft[0];
var dh = bottomRight[1] - topLeft[1];
image.id = "pic";
image.crossOrigin = "anonymous";
image.onload = function () {
sx = sx * initialZoom;
sy = sy * initialZoom;
dw = dw * initialZoom;
dh = dh * initialZoom;
link.href = crop(image, sx, sy, dw, dh);
link.click();
};
image.src = canvas.toDataURL("image/png");
});
map.addInteraction(draw);
function crop(img, sx, sy, dw, dh) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = dw;
canvas.height = dh;
ctx.drawImage(img, sx, sy, dw, dh, 0, 0, dw, dh);
return canvas.toDataURL("image/png");
}
<link href="https://openlayers.org/en/v4.6.4/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script>
<div id="map" class="map"></div>
<a id="export-png" class="btn" download="map.png"> </a>
摘录来自@dube的答案,我只修改了image.onload
并将initialZoom
存储在第一行.
Snippet comes from @dube's answer, and I modified image.onload
only and stored initialZoom
in the first line.
这篇关于无法从画布上制作一块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!