Home > Software engineering >  Saving a div contains a geomap as an Image
Saving a div contains a geomap as an Image

Time:08-18

I want to save the showing map in my div as an image. I tried the following code but it does not show the map content but just the map contollers.

I used the snippet but Actually I don't know why it doesn't show the appened picture on the snippet. it shows the appened picture (without map content) for me.

$(function () {
    var map = L.map('map').setView([10.505, 20], 2);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19,
        attribution: '© OpenStreetMap'
    }).addTo(map);
    map.zoomControl.setPosition('bottomright');

});


$("#geo-btn").on("click", function (e) {


    var container = L.DomUtil.get('map');

    if (container != null) {
        container._leaflet_id = null;
    }
    var map = L.map('map').setView([10.505, 20], 2);


    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19,
        attribution: '© OpenStreetMap'
    }).addTo(map);

    var states = JSON.parse(`[{
        "type": "Feature",
        "properties": { "party": "Republican" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-104.05, 48.99],
                [-97.22, 48.98],
                [-96.58, 45.94],
                [-104.03, 45.94],
                [-104.05, 48.99]
            ]]
        }
    }, {
        "type": "Feature",
        "properties": { "party": "Democrat" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-109.05, 41.00],
                [-102.06, 40.99],
                [-102.03, 36.99],
                [-109.04, 36.99],
                [-109.05, 41.00]
            ]]
        }
    }]`);

    L.geoJSON(states, {
        style: function (feature) {
            switch (feature.properties.party) {
                case 'Republican': return { color: "#ff0000" };
                case 'Democrat': return { color: "#0000ff" };
            }
        }
    }).addTo(map);
});

$("#img-save").on("click", function () {
    html2canvas(document.getElementById("map")).then(canvas => {
        document.body.appendChild(canvas);
    });

});
#map {
    height: 500px;
    border: red solid 1px;

}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
        integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9 580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
        crossorigin="" />
    <!-- Make sure you put this AFTER Leaflet's CSS -->
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
        integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
        crossorigin=""></script>
    <script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
    <title>Geo</title>
</head>

<body>
 <body>
<button id="geo-btn"> Click to Show</button>
 <button id="img-save">Show Image</button>
<div id="map"></div>

<div id="result-img"></div>


</body>


</body>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

</html>

CodePudding user response:

I think this should work for you

$(function() {
  const map = L.map('map').setView([10.505, 20], 2);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '© OpenStreetMap'
  }).addTo(map);
  map.zoomControl.setPosition('bottomright');
});
$("#geo-btn").on("click", function(e) {
  const container = L.DomUtil.get('map');
  if (container != null) {
    container._leaflet_id = null;
  }
  const map = L.map('map').setView([10.505, 20], 2);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '© OpenStreetMap'
  }).addTo(map);
  const states = JSON.parse(`[{
        "type": "Feature",
        "properties": { "party": "Republican" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-104.05, 48.99],
                [-97.22, 48.98],
                [-96.58, 45.94],
                [-104.03, 45.94],
                [-104.05, 48.99]
            ]]
        }
    }, {
        "type": "Feature",
        "properties": { "party": "Democrat" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-109.05, 41.00],
                [-102.06, 40.99],
                [-102.03, 36.99],
                [-109.04, 36.99],
                [-109.05, 41.00]
            ]]
        }
    }]`);
  L.geoJSON(states, {
    style: function(feature) {
      switch (feature.properties.party) {
        case 'Republican':
          return {
            color: "#ff0000"
          };
        case 'Democrat':
          return {
            color: "#0000ff"
          };
      }
    }
  }).addTo(map);
});

$("#img-save").on("click", function() {
  const clone = document.getElementById("map").cloneNode(true);
  document.getElementById('foo').appendChild(clone);
});
#map {
  height: 500px;
  border: red solid 1px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9 580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
  <!-- Make sure you put this AFTER Leaflet's CSS -->
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
  <script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
  <title>Geo</title>
</head>



<body>
  <button id="geo-btn"> Click to Show</button>
  <button id="img-save">Show Image</button>
  <div id="map"></div>

  <div id="result-img"></div>


</body>


<div id="foo"></div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

</html>

you just need these lines:

  const clone = document.getElementById("map").cloneNode(true);
  document.getElementById('foo').appendChild(clone);

I hope this helps

CodePudding user response:

Check out: https://jsfiddle.net/PatrickHume/1rscqwkL/1/, as the image download doesn't work in SO's code runner, click the 'Click to Show' first then click 'Show Image' and it will download the image

it uses: https://github.com/tsayen/dom-to-image and https://github.com/eligrey/FileSaver.js/

$(function() {
  const map = L.map('map').setView([10.505, 20], 2);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '© OpenStreetMap'
  }).addTo(map);
  map.zoomControl.setPosition('bottomright');
});
$("#geo-btn").on("click", function(e) {
  const container = L.DomUtil.get('map');
  if (container != null) {
    container._leaflet_id = null;
  }
  const map = L.map('map').setView([10.505, 20], 2);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '© OpenStreetMap'
  }).addTo(map);
  const states = JSON.parse(`[{
        "type": "Feature",
        "properties": { "party": "Republican" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-104.05, 48.99],
                [-97.22, 48.98],
                [-96.58, 45.94],
                [-104.03, 45.94],
                [-104.05, 48.99]
            ]]
        }
    }, {
        "type": "Feature",
        "properties": { "party": "Democrat" },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[
                [-109.05, 41.00],
                [-102.06, 40.99],
                [-102.03, 36.99],
                [-109.04, 36.99],
                [-109.05, 41.00]
            ]]
        }
    }]`);
  L.geoJSON(states, {
    style: function(feature) {
      switch (feature.properties.party) {
        case 'Republican':
          return {
            color: "#ff0000"
          };
        case 'Democrat':
          return {
            color: "#0000ff"
          };
      }
    }
  }).addTo(map);
  $("#img-save").on("click", function() {
    const clone = document.getElementById("map").cloneNode(true);
    document.getElementById('foo').appendChild(clone);
    domtoimage.toBlob(document.getElementById('foo'))
      .then(function(blob) {
        window.saveAs(blob, 'my-node.png');
      });
  });

});
#map {
  height: 500px;
  border: red solid 1px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9 580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
  <!-- Make sure you put this AFTER Leaflet's CSS -->

  <title>Geo</title>
</head>
<body>
  <button id="geo-btn"> Click to Show</button>
  <button id="img-save">Show Image</button>
  <div id="map"></div>

  <div id="result-img"></div>


</body>


<div id="foo"></div>



<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
<script src="https://cdn.bootcss.com/dom-to-image/2.6.0/dom-to-image.min.js"></script>

</html>

Hope this helps

  • Related