Issue with extending DragZoomingTool

I’m using GoJS over Leaflet using typescript, and I’m attempting to override DragZoomingTool so it will behave according to Leaflet’s typical behavior which is that a zoom is effected on shift, drag to create a bounding box.

See Implementing Drag Zooming Tool in TS / Angular 2+ for some history.

I’m having a problem where the Rect’s coordinates are not translating to expected latlongs. I have all of my other diagram parts correctly positioning on the map, and for them the .containerPointToLatLong is working fine during binding conversion, so I’m not sure what is special about this case.

Here’s my extension:

export class MapDragZoomingTool extends DragZoomingTool {

public readonly name: string = “MapDragZooming”;

private _theMap : L.Map;

constructor(leafletMap: L.Map) {
super();

this._theMap = leafletMap;

}

public doActivate() {

if (!this.diagram.lastInput.shift) return;

DragZoomingTool.prototype.doActivate.call(this);

this.doMouseMove();

};

public doDeactivate() {

if (!this.diagram.lastInput.shift) return;

DragZoomingTool.prototype.doDeactivate.call(this);

};

public doMouseMove() {

if (!this.diagram.lastInput.shift) return;

this._theMap.dragging.disable();

DragZoomingTool.prototype.doMouseMove.call(this);

};

public doMouseUp() {

this._theMap.dragging.enable();

DragZoomingTool.prototype.doMouseUp.call(this);

};

public zoomToRect(r: go.Rect) {
if (r.width < 0.1) return;
let observed = this.zoomedDiagram;
if (observed === null) observed = this.diagram;
if (observed === null) return;

let ll_topleft = (this._theMap.containerPointToLatLng([r.top, r.left]));
let ll_bottomright = (this._theMap.containerPointToLatLng([r.bottom, r.right]));

console.log("top, left, bottom, right:", r.top, r.left, r.bottom, r.right);
console.log("ll_topleft:", ll_topleft);
console.log("ll_bottomright:", ll_bottomright);

console.log("fitting bounds:", [[ll_topleft.lat, ll_topleft.lng], [ll_bottomright.lat, ll_bottomright.lng]]);

this._theMap.fitBounds([[ll_topleft.lat, ll_topleft.lng], [ll_bottomright.lat, ll_bottomright.lng]]);

};
}

Here is the console dump of me selecting around downtown Houston:

The location calculated by .containerPointToLatLong is somewhere north east. The commonality is that the calculated places are north east. Can you see any issue with my logic for capturing the rectangle and converting to lat/long?

Thanks,

K

I’m not sure the exact behavior that you want, but it is normally the case that one overrides Tool.canStart in order to determine, at least initially, whether a particular Tool should run or not.

As it is it appears that your code allows that DragZoomingTool to run but not to do anything if the Shift key modifier is true.

I don’t see anything wrong with your lat-lng code, but I’m not an expert. It does appear that you have not confused X and Y when dealing with Longitude and Latitude, but again I’m not that familiar with it.

is a documentPoint the same as a container point?

I was able to get this working by rewriting zoomToRect a bit (compare with last version). Here’s my final solution (this zooms to user’s selected bounding box over a Leaflet map). Thank you for the tips on .canStart:

export class MapDragZoomingTool extends DragZoomingTool {
  public readonly name: string = "MapDragZooming";

  private _theMap : L.Map;

  constructor(leafletMap: L.Map) {
    super();

    this._theMap = leafletMap;

  }

  public canStart(): boolean {
    if (!this.isEnabled) return false;
    let diagram = this.diagram;
    if (diagram === null) return false;
    let e = diagram.lastInput;
    // require left button & that it has moved far enough away from the mouse down point, so it isn't a click
    if (!e.left) return false;
    // don't include the following checks when this tool is running modally
    if (diagram.currentTool !== this) {
      if (!this.isBeyondDragSize()) return false;
      // must wait for "delay" milliseconds before that tool can run
      if (e.timestamp - diagram.firstInput.timestamp < this.delay) return false;
    }
    return e.shift;
  };

  public doActivate() {

    this._theMap.dragging.disable();

    DragZoomingTool.prototype.doActivate.call(this);

    this.doMouseMove();
  };
  //
  public doDeactivate() {

    this._theMap.dragging.enable();

    DragZoomingTool.prototype.doDeactivate.call(this);

  };

  public zoomToRect(r: go.Rect) {
    if (r.width < 0.1) return;
    let observed = this.zoomedDiagram;
    if (observed === null) observed = this.diagram;
    if (observed === null) return;

    let start = this.diagram.firstInput.documentPoint;
    let latest = this.diagram.lastInput.documentPoint;

    let ll1 = (this._theMap.containerPointToLatLng([start.x, start.y]));
    let ll2 = (this._theMap.containerPointToLatLng([latest.x, latest.y]));

    this._theMap.fitBounds(new L.LatLngBounds(ll1,ll2));

  };
}