Search code examples
javascriptopenlayersheatmapkmlkmz

How can I add this image to the map stretching over an extent specified in degrees?


I have a codepen at https://codepen.io/ericg_off/pen/gOqmpEE

While I would like to have made this code available as a working snippet, it exceeds those limits. The value of washb64 can be found in the codepen.

washb64 is a base64 encode kmz file. The data within represents a heatmap in Washington, DC. I need to be able to take this data and display it in OpenLayers. While OpenLayers does support kml, it does not support the GroundOverlay. My thought was to use an OpenLayer Image Layer with a custom projection and place the static image in the right spot. However, my code is not working.

The degrees used in the project were pulled from the kml file.

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Folder>
    <GroundOverlay>
      <Icon>
        <href>wash-dc.png</href>
      </Icon>
      <LatLonBox>
        <north>38.9098677066083098</north>
        <south>38.8880492619716591</south>
        <east>-77.0492054375858260</east>
        <west>-77.0124290658545902</west>
        <rotation>0</rotation>
      </LatLonBox>
    </GroundOverlay>
  </Folder>
</kml>

The end result should look similar to how the kmz file looks when loaded into Google Earth.

google earth

I am sure there are many things wrong with the code, but I am not sure what or how to fix it.

const washb64 = ''

const north = 38.9098629826801456;
const south = 38.8880073821501711;
const east = -77.0497762322933539;
const west = -77.0120905091252439;

async function loadHeatmapData() {
  const zipFile = new JSZip();

  await zipFile.loadAsync(washb64, { base64: true });

  const imageFile = zipFile.file("wash-dc.png");
  const data = await imageFile.async("arraybuffer");
  const url = URL.createObjectURL(new Blob([data]));

  const projection = new ol.proj.Projection({
    code: "heatmap",
    units: "degrees",
    extent: [west, south, east, north]
  });

  const imageLayer = new ol.layer.Image({
    source: new ol.source.ImageStatic({
      attributions: "wash dc",
      url: url,
      projection: projection,
      imageExtent: [0, 0, 1024, 1024]
    })
  });

  const map = new ol.Map({
    target: "map",
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      imageLayer
    ],
    view: new ol.View({
      projection: "EPSG:4326",
      center: [-77.05, 38.9],
      zoom: 15
    })
  });
}

loadHeatmapData();
#map {
  height: 512px;
  width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>

<div id="map"></div>


Solution

  • The projection should be EPSG:4326, the image extent should be in degrees

      const imageLayer = new ol.layer.Image({
        source: new ol.source.ImageStatic({
          attributions: "wash dc",
          url: url,
          projection: "EPSG:4326",
          imageExtent: [west, south, east, north]
        })
      });