How to use Leaflet flyTo() with unproject() and GeoJSON data on a large raster image?

假装没事ソ 提交于 2020-01-14 03:18:07

问题


I'm building a story map with Leaflet using a large image sliced into tiles rather than 'real world' map data. I'm using this plugin: https://commenthol.github.io/leaflet-rastercoords/ and this repo: https://github.com/jackdougherty/leaflet-storymap

Loading my GeoJSON data and unprojecting the coordinates correctly plots them on my image map:

$.getJSON('map.geojson', function(data) {
  var geojson = L.geoJson(data, {
  // correctly map the geojson coordinates on the image
    coordsToLatLng: function (coords) {
      return rc.unproject(coords)
  },

But when I get to onEachFeature, I hit the wall with map.flyTo(), which is calling geometry.coordinates from my JSON file, but not unprojecting them so flyTo() is interpreting them as geospatial coordinates way off the map:

map.flyTo([feature.geometry.coordinates[1], feature.geometry.coordinates[0] ], feature.properties['zoom']);

I tried passing the unprojected coordinates to variables and then to map.flyTo() and variations on nesting functions, such as map.flyTo.unproject(..., but no luck.

How do I pass my raster coordinates to flyTo()?

I'm not only new to Leaflet, but new to JavaScript. I hacked my way this far, but I'm stumped. I'm sure the solution is obvious. Any help is greatly appreciated.


回答1:


In your case you would probably just need to use rc.unproject to convert your coordinates into LatLng that you can pass to flyTo:

map.flyTo(
  rc.unproject(feature.geometry.coordinates),
  feature.properties['zoom']
);

That being said, I must admit I do not exactly see the point of using leaflet-rastercoords plugin, since you can easily do the same by following the Leaflet tutorial "Non-geographical maps".

var yx = L.latLng;

var xy = function(x, y) {
  if (L.Util.isArray(x)) { // When doing xy([x, y]);
    return yx(x[1], x[0]);
  }
  return yx(y, x); // When doing xy(x, y);
};

With this, whenever you want to convert your "raster" coordinates into something usable by Leaflet, you would just use xy(x, y) with x being your horizontal value, and y your vertical one.

The added benefit is that many other things will become easily compatible.

Since you use tiles instead of a single image (that is stretched with ImageOverlay in the tutorial in order to fit the coordinates), you should modify the CRS transformation, so that at zoom 0, your tile 0/0/0 fits your entire coordinates. See also Leaflet custom coordinates on image

I.e. in the case of leaflet-rastercoords example:

  • Original raster image size: 3831 px width x 3101 px height
  • Tiles size: 256 x 256 px
  • Vertical "raster" coordinates are increasing while going down (whereas in the Leaflet tutorial, they increase going up, like latitude).
  • Tile 0/0/0 actually covers more than the original image, as if the latter were 4096 x 4096 px (the rest is filled with white)

Determination of the new CRS:

  • Tile 0/0/0 should cover coordinates from top-left [0, 0] to bottom-right [4096, 4096] (i.e. 256 * 2^4 = 256 * 16 = 4096) => transformation coefficients a and c should be 1/16
  • No offset needed => offsets b and d are 0
  • No reversion of y vertical coordinate => c is positive

Therefore the new CRS to be used would be:

L.CRS.MySimple = L.extend({}, L.CRS.Simple, {
  //                      coefficients: a      b    c     d
  transformation: new L.Transformation(1 / 16, 0, 1 / 16, 0)
});

Now your flyTo is very similar, but many other things are also compatible:

map.flyTo(
  xy(feature.geometry.coordinates),
  feature.properties['zoom']
);

Demo adapted from leaflet-rastercoords example, and using an extra plugin to demonstrate compatibility: https://plnkr.co/edit/Gvei5I0S9yEo6fCYXPuy?p=preview



来源:https://stackoverflow.com/questions/44054833/how-to-use-leaflet-flyto-with-unproject-and-geojson-data-on-a-large-raster-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!