我希望与地图进行这样的交互,当用户选择地图上的某个区域时,会从该区域创建图像。我在这个fiddle中做了一个最小化且完全可重复的例子。最重要的部分是这种作物功能:
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");
}
此功能从选定区域创建一个块。选择的方式如下:
但这就是我得到的结果:
所以,我的大块是完全错误的。但更有趣的是,在某些任意计算机和某些任意浏览器中,块是正确的。所以,我真的需要让这个代码跨平台和跨浏览器。
答案 0 :(得分:2)
但问题是,似乎从JavaScript代码中不可能知道这个系统/浏览器参数 - 我的意思是初始页面缩放级别。
实际上有window.devicePixelRatio
只需使用它代替ratio_W
和ratio_H
,它就会开始工作:
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>
&#13;
Snippet来自@ dube的回答,我修改了image.onload
并在第一行存储了initialZoom
。
答案 1 :(得分:1)
我猜想你混合了预测。但这不是错误,你只是混淆了一些变量。这是存储选择范围的不必要的复杂方式。
coordinate
的{{1}}已经具有范围,定义为两个坐标。只需使用它们并删除循环。不知道为什么它首先出现在那里。
geometryFunction
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 () {
var ratio_W = canvas.clientWidth / image.naturalWidth;
var ratio_H = canvas.clientHeight / image.naturalHeight;
//with or without scaling image chunk is incorrect
sx = sx * ratio_W;
sy = sy * ratio_H;
dw = dw * ratio_W;
dh = dh * ratio_H;
// console.log(sx, sy, dw, dh, ratio_H);
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");
}