让传单不要居中

时间:2018-01-25 19:07:40

标签: leaflet

我在地图上有一条线索,用户可以跟随"通过鼠标悬停在图表上(时间和速度)。如果用户放大很多,则部分路径可能不可见。当用户想要查看未显示的部分路径时,我使用panTo方法...

传单的panTo方法目前也居中。我不想居中,我希望地图移动足够来显示一个点。 (panTo的问题是导致过多的地图滚动和恶劣的用户体验。)

我尝试过更改边界,但有时会缩小(不需要的)副作用。

任何方式我都可以做一个" minimal"哑剧?

这是一个(工作但未经修改)的解决方案; map是我们自己的map wrapper实用程序类,lmap是typescript中的leaflet map对象,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));
 }

3 个答案:

答案 0 :(得分:3)

首先,使用map.getPixelBounds()获取地图的边界(以CRS原点为单位测量)。然后,使用map.project(latlng, map.getZoom())获取您感兴趣的点的坐标(以CRS原点为单位)。

如果您对此“来自CRS原点的像素”感到困惑,请阅读http://leafletjs.com/examples/extending/extending-2-layers.html处的“Pixel Origin”部分。

一旦你有这些像素坐标,检查点是否在视口内部应该是一个简单的事情,如果没有,那么每个方向的距离应该是多远。

答案 1 :(得分:0)

http://jsfiddle.net/jcollin6/b131tobj/2/

应该给你你想要的东西

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;
  }
});

答案 2 :(得分:0)

使用这种方式

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