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 exa
Solution 1:
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.
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 = newImage(),
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);
functioncrop(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");
}
<linkhref="https://openlayers.org/en/v4.6.4/css/ol.css" /><scriptsrc="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script><divid="map"class="map"></div><aid="export-png"class="btn"download="map.png"> </a>
Snippet comes from @dube's answer, and I modified image.onload
only and stored initialZoom
in the first line.
Solution 2:
I would have guessed that you mixed projections. But that was not the bug, you simply mixed up some variables. It's the unecessary complicated way of storing the selection extent.
coordinate
of geometryFunction
already has the extent, defined as two coordinates. Just use those and remove the loop. No idea why it's there in the first place.
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 = newImage(),
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);
functioncrop(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");
}
<linkhref="https://openlayers.org/en/v4.6.4/css/ol.css"rel="stylesheet"/><scriptsrc="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script><divid="map"class="map"></div><aid="export-png"class="btn"download="map.png"> </a>
Post a Comment for "Unable To Make A Chunk From Canvas"