Leaflet 传单盘不居中

Leaflet 传单盘不居中,leaflet,Leaflet,我在地图上有一条轨迹,用户可以通过鼠标在图形上“跟踪”(时间和速度)。如果用户放大很多,部分轨迹可能不可见。当用户希望看到未显示的轨迹部分时,我使用panTo方法 传单的panTo方法目前也是居中。我不想居中,我想让地图移动到足以显示一个点。(panTo的问题在于它会导致地图过度滚动和恶劣的用户体验。) 我尝试过改变边界,但这有(不必要的)副作用,有时会缩小 我能做一个“最小”的潘托吗 这是一个(有效但未抛光的)解决方案;map是我们自己的map wrapper实用程序类,lmap是types

我在地图上有一条轨迹,用户可以通过鼠标在图形上“跟踪”(时间和速度)。如果用户放大很多,部分轨迹可能不可见。当用户希望看到未显示的轨迹部分时,我使用panTo方法

传单的panTo方法目前也是居中。我不想居中,我想让地图移动到足以显示一个点。(panTo的问题在于它会导致地图过度滚动和恶劣的用户体验。)

我尝试过改变边界,但这有(不必要的)副作用,有时会缩小

我能做一个“最小”的潘托吗


这是一个(有效但未抛光的)解决方案;map是我们自己的map wrapper实用程序类,lmap是typescript中的一个传单映射对象,toxy()是将lat/long值转换为x/y值的方法

 if (!this.lmap.getBounds().contains(latlng)) {
    let target = this.map.toxy(latlng);

    let nw = this.map.toxy(this.lmap.getBounds().getNorthWest());
    let se = this.map.toxy(this.lmap.getBounds().getSouthEast());
    let x = 0, y = 0;

    let margin = 75;
    if (target.y < nw.y)
       y = (-1 * (nw.y - target.y)) - margin;
    else if (target.y > se.y)
       y = (target.y - se.y) + margin;

    if (target.x < nw.x)
       x = (-1 * (nw.x - target.x)) - margin;
    else if (target.x > se.x)
       x = (target.x - se.x) + margin;

    this.lmap.panBy(new L.Point(x, y));
 }
if(!this.lmap.getBounds().contains(latlng)){
让target=this.map.toxy(latlng);
设nw=this.map.toxy(this.lmap.getBounds().getNorthWest());
设se=this.map.toxy(this.lmap.getBounds().getSouthwest());
设x=0,y=0;
设保证金=75;
如果(目标yse.y)
y=(target.y-se.y)+保证金;
如果(目标xse.x)
x=(target.x-se.x)+保证金;
这个.lmap.panBy(新的L点(x,y));
}

首先,使用获取地图的边界(从CRS原点以像素为单位测量)。然后,使用获取感兴趣点的坐标(以CRS原点的像素为单位)

如果您对“来自CRS原点的像素”感到困惑,请阅读下面的“像素原点”部分

获得这些像素坐标后,只需检查点是否在视口内,如果不在视口内,则检查点在每个方向上的距离。

你应该给你想要的

function clamp(n,lower,upper) {
  return Math.max(lower, Math.min(upper, n));
}
//Shamelessly stolen from https://gist.github.com/dwtkns/d5b9b60285b8b0067c53
function getNearestPointInPerimeter(l,t,w,h,x,y) {
  var r = l+w,
      b = t+h;

  var x = clamp(x,l,r),
      y = clamp(y,t,b);

  var dl = Math.abs(x-l),
      dr = Math.abs(x-r),
      dt = Math.abs(y-t),
      db = Math.abs(y-b);

  var m = Math.min(dl,dr,dt,db);

  return (m===dt) ? {x: x, y: t} :
         (m===db) ? {x: x, y: b} :
         (m===dl) ? {x: l, y: y} : {x: r, y: y};
}

L.ExtendedMap = L.Map.extend({
  panInside: function (latlng, pad, options) {
    var padding = pad ? pad : 0;
    var pixelBounds = this.getPixelBounds();
    var center = this.getCenter();
    var pixelCenter = this.project(center);
    var pixelPoint = this.project(latlng);
    var sw = pixelBounds.getBottomLeft();
    var ne = pixelBounds.getTopRight();
    var topLeftPoint = L.point(sw.x + padding, ne.y + padding);
    var bottomRightPoint = L.point( ne.x - padding, sw.y - padding);
    var paddedBounds = L.bounds(topLeftPoint, bottomRightPoint);

    if (!paddedBounds.contains(pixelPoint)) {
      this._enforcingBounds = true;

      var nearestPoint = getNearestPointInPerimeter(
        sw.x + padding, 
        ne.y + padding, 
        ne.x - sw.x - padding * 2, 
        sw.y - ne.y - padding * 2, 
        pixelPoint.x, 
        pixelPoint.y
      );
      var nearestPixelPoint = L.point(nearestPoint.x,nearestPoint.y)
      var diffPixelPoint = nearestPixelPoint.subtract(pixelPoint);
      var newPixelCenter = pixelCenter.subtract(diffPixelPoint);
      var newCenter = this.unproject(newPixelCenter);
      if (!center.equals(newCenter)) {
        this.panTo(newCenter, options);
      }
      this._enforcingBounds = false;
    }
    return this;
  }
});
这样

map.panTo([lat, lng]);
map.setZoom(Zoom);

一旦你知道离点有多少像素,你就可以使用
map.panBy()
将其平移到视图中。是的,我最终使用了panBy(),更不用说地图滚动了,这样用户体验会更好。