Skip to content Skip to sidebar Skip to footer

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">&nbsp;</a>

Snippet comes from @dube's answer, and I modified image.onloadonly 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">&nbsp;</a>

Post a Comment for "Unable To Make A Chunk From Canvas"