简体   繁体   中英

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

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.

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

Ie 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)

来自Leaflet-Rastercoords示例的图块0/0/0

Determination of the new CRS:

  • Tile 0/0/0 should cover coordinates from top-left [0, 0] to bottom-right [4096, 4096] (ie 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM