2

I have a leaflet map which consists of a tile layer and above an imageOverlay which is semi transparently showing temperature distribution as colored areas. The Overlay is placed at certain bounds within the tile layer. When I click somewhere on the the overlay, I want to figure out what color the pixel at that point has.

My problem is to project the clicked position onto the imageOverlay respecting the offset of the imageOverlay to the visible map and the zoom level. Eventually I want to get the pixel coordinates at the image (at it's natural resolution)

The code roughly looks like this:

var imgUrl = 'https://somewhere.somewhere/myImage.png';
var tilesUrl = 'https://somewhere.somewhere/{z}/{x}/{y}.png';
var tilesBounds = [...];
var imgBounds = [...];
var latlng = [...];

var mymap = L.map('mapid').setView(latlng, 9);
L.tileLayer(tilesUrl, {
    attribution: 'TILES',
    maxZoom: 12,
    minZoom: 7,
    id: 'tiles',
    tms: true,
    maxBounds: tilesBounds
}).addTo(mymap);

var imgOverlay = L.imageOverlay(imgUrl, imgBounds {
    attribution: 'dataimg',
    opacity: '0.4',
    id: 'dataImg',
    interactive: true
}).addTo(mymap);

imgOverlay.on('click',
  (e) => {

    var x = ???;
    var y = ???;

    var color = getColorAt(x, y);

  }
)
Twirisng
  • 23
  • 2

1 Answers1

3

One possible solution would be to

For example, imgWidth and imgHeight being the original dimensions of the image:

imgOverlay.on('click', (leafletEvent) => {
    // see https://stackoverflow.com/a/42111623/1071630
    var e = leafletEvent.originalEvent;
    var rect = e.target.getBoundingClientRect();
    var zoomedX = e.clientX - rect.left; //x position within the element.
    var zoomedY = e.clientY - rect.top;  //y position within the element

    const x = Math.round(zoomedX * imgWidth / rect.width);
    const y = Math.round(zoomedY * imgHeight / rect.height);
    console.log(x, y);
});

var map = L.map('map').setView([48.854, 2.2922926], 14);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

const bounds = [[48.85, 2.28], [48.86, 2.29]]
const imgOverlay = L.imageOverlay('https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Tour_Eiffel_en_mai_2014.JPG/450px-Tour_Eiffel_en_mai_2014.JPG', bounds, {
    attribution: 'Nicolas Halftermeyer / CC BY-SA (https://creativecommons.org/licenses/by-sa/3.0)',
    id: 'dataImg',
    interactive: true
}).addTo(map);

const imgWidth = 450, imgHeight = 600;
imgOverlay.on('click', (leafletEvent) => {
    // see https://stackoverflow.com/a/42111623/1071630
    var e = leafletEvent.originalEvent;
    var rect = e.target.getBoundingClientRect();
    var zoomedX = e.clientX - rect.left; //x position within the element.
    var zoomedY = e.clientY - rect.top;  //y position within the element

    const x = Math.round(zoomedX * imgWidth / rect.width);
    const y = Math.round(zoomedY * imgHeight / rect.height);
    document.getElementById('log').innerHTML+= x+","+y+"<br>";
});
#map {width: 400px; height: 200px;}
#log {position: absolute; top: 0; right:10px; width: 100px;}
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" rel="stylesheet"/>
<div style='position: relative'>
  <div id="map"></div>
  <div id='log'></div>
 </div>
nikoshr
  • 32,926
  • 33
  • 91
  • 105