Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the d3 svg points to stay in their correct position on the leaflet map when zooming?

Tags:

d3.js

leaflet

var map = L.map('mapid').setView([10.0, 15.0], 2);

L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/light-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic2FidW1hZm9vIiwiYSI6ImNqMWE3cnlqcTA5dncyd216YjI0bnY4dGEifQ.fgmXgmkvialdBd3D405_BA', {
attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
maxZoom: 18,
id: 'mapbox.streets',
accessToken: 'pk.eyJ1Ijoic2FidW1hZm9vIiwiYSI6ImNqMWE3cnlqcTA5dncyd216YjI0bnY4dGEifQ.fgmXgmkvialdBd3D405_BA'
}).addTo(map);

L.svg().addTo(map);

var svg = d3.select(map.getPanes().overlayPane).select('svg');

var g = svg.append('g').attr('class', 'leaflet-zoom-hide');

const URL = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&limit=200'

function getEarthquakeData() {
  fetch(URL)
  .then((results) => {
return results.json();
  })
  .then((result) => {

function projectPoint(x,y) {
  var point = map.latLngToLayerPoint(new L.LatLng(y,x));
  this.stream.point(point.x, point.y);
}

var transform = d3.geoTransform({point: projectPoint}),
path = d3.geoPath().projection(transform);

function applyLatLngToLayer(d){
  var y = d.geometry.coordinates[1];
  var x = d.geometry.coordinates[0];
  return map.latLngToLayerPoint(new L.LatLng(y,x));
}

// console.log(result.features);
// result.features.forEach(function(d) {
//   d.LatLng = new L.LatLng(d.geometry.coordinates[1],
//     d.geometry.coordinates[0])
//   });

var circle = g.selectAll('circle')
.data(result.features)
.enter().append('circle')
.style('fill','darkred')
.attr('r', 2)
.attr('opacity',0.5);

function update() {

  circle.attr("transform",
  function(d) {
    return "translate("+
    applyLatLngToLayer(d).x+","+
    applyLatLngToLayer(d).y+")";
  });

  var bounds = path.bounds(result),
  topLeft = bounds[0],
  bottomRight = bounds[1];

  svg.attr("width", bottomRight[0] - topLeft[0])
    .attr("height", bottomRight[1] - topLeft[1])
    .style("left", topLeft[0] + "px")
    .style("top", topLeft[1] + "px");

  g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");

  }

  map.on('viewreset', update);
  update();

  })

}


getEarthquakeData();

The above code will add points to a leaflet map once it fetches the data I'm interested in mapping. The problem is that when I zoom in on the map all of the points remain in their same position while the map background changes view. The points are not actually "affixed" to the correct location in any view besides the opening view. I know this has something to do with the way I'm updating the view but I haven't been able to figure it out. Please help! Thanks in advance.

like image 242
user2097478 Avatar asked Oct 23 '25 23:10

user2097478


1 Answers

I suspect you are using version 1.*, if so then this is a known issue:

https://github.com/Leaflet/Leaflet/issues/5016

Switch from the viewreset event to the moveend event and you should be ok.

like image 125
iH8 Avatar answered Oct 27 '25 01:10

iH8