ngx-mapbox-gl icon indicating copy to clipboard operation
ngx-mapbox-gl copied to clipboard

mglDraggable doesn't work without (mouseEnter) in mgl-layer

Open vamcs opened this issue 5 years ago • 2 comments

I don't seem to be able to add mglDraggable to mgl-features inside a ngFor loop. The dragging function just simply doesn't work.

<mgl-geojson-source id="route">
    <ng-container *ngFor="let waypoint of [ [17.6392731, 59.2019309],
                                        [17.6212388277054, 59.2010590531024],
                                        [17.6082654576989, 59.2042359987876],
                                        [17.6118, 59.20358]]; trackBy: trackByFn">
        <mgl-feature
            [properties]="" 
            [geometry]="{ 'type': 'Point', 'coordinates': waypoint }"
            [mglDraggable]="layer"
            (dragStart)="onDragStop($event)"></mgl-feature>
    </ng-container>
</mgl-geojson-source>
<mgl-layer #layer 
              id="route" 
              type="circle" 
              source="route"
              [layout]="{ 'visibility': 'visible' }"
              [paint]="{  'circle-radius': 10, 
                          'circle-color': 'red', 
                          'circle-stroke-color': 'white',
                          'circle-stroke-width': 2 }"></mgl-layer>

But if I add each of the mgl-features manually like below it works and I can drag any of the circles independently.

<mgl-feature
            [properties]="" 
            [geometry]="{ 'type': 'Point', 'coordinates': [lng, lat] }"
            [mglDraggable]="layer"
            (dragStart)="onDragStop($event)"></mgl-feature>

Am I missing something? Or does this look like a bug?

Thanks!

vamcs avatar Jun 10 '19 13:06 vamcs

What I could observe so far is that it actually works to have a loop of mgl-features, but:

  1. if I remove the trackBy function from mgl-feature the dragging stops working;
  2. if I add either a loop or an if around mgl-geojson-source (I'll need several sources) the dragging doesn't work either.

And all of that fails silently. Just for reference, the trackByFn is:

trackByFn(index, item) {
	return index; // or item.id
}

Another update: apparently, the problem occurs when the data isn't available before the initialization of the directive. Since I need to wait for an http call for my coordinates and I only make that call after the map starts up, the dragging simply doesn't "start up". I tested creating one of my objects manually at OnInit and the dragging actually worked inside a loop of mgl-geojson-sources and mgl-features.

vamcs avatar Jun 13 '19 11:06 vamcs

I have managed to reproduce this. The problem was that I wasn't listening to the (mouseEnter) and (mouseLeave) events from the layers and for some reason they just won't work properly if I don't listen to these outputs.

I forked the drag example and removed the two properties from the layer and simulated a similar situation as I described up here in the issue.

https://stackblitz.com/edit/angular-29siqa

The first set of points that load with the map have the dragging working fine, but as soon as you add more layers afterwards by clicking on ADD, the dragging isn't enabled.

Once I added that to my layers in my project, the dragging worked, and this makes me believe that the event isn't being attached properly to the layer.


Pasting the code here in case stackblitz doesn't work.

import { Component } from '@angular/core';
import { MapMouseEvent } from 'mapbox-gl';

@Component({
  selector: 'showcase-demo',
  template: `
  <mgl-map
    [style]="'mapbox://styles/mapbox/streets-v9'"
    [zoom]="[2]"
    [center]="[0, 0]"
  >
  <ng-container *ngFor="let i of i_array">
    <mgl-geojson-source
      [id]="i+''"
    >
      <ng-container *ngFor="let j of j_array">
        <mgl-feature
          [properties]=""
          [geometry]="{
            'type': 'Point',
            'coordinates': [i, j]
          }"
          [mglDraggable]="targetLayer"
        ></mgl-feature>
      </ng-container>
    </mgl-geojson-source>
    <mgl-layer
      #targetLayer
      [id]="i+''"
      type="circle"
      [source]="i+''"
      [paint]="layerPaint"
    ></mgl-layer>
    </ng-container>
    <mgl-control position="bottom-left">
      <mat-card>
        <button mat-raised-button color="primary" (click)="pushToArray()">ADD</button>
      </mat-card>
    </mgl-control>
  </mgl-map>
  `,
  styleUrls: ['./examples.css']
})
export class NgxDragAPointComponent {
  i_array = [1]
  j_array: number[] = []
  constructor() {
    for(let i of [1,2,3,4]) { 
      this.j_array.push(35 * Math.random())
    }
  }

  pushToArray() {
    this.i_array.push(this.i_array.length + 10);
  }

  layerPaint = {
    'circle-radius': 10,
    'circle-color': '#3887be'
  };

  coordinates = [0, 0];

  onDragStart(event: MapMouseEvent) {
    // console.log('onDragStart', event);
  }

  onDragEnd(event: MapMouseEvent) {
    // console.log('onDragEnd', event);
  }

  onDrag(event: MapMouseEvent) {
    console.log('onDrag', event);
    this.coordinates = event.lngLat.toArray();
  }

  changeColor(color: string) {
    this.layerPaint = { ...this.layerPaint, 'circle-color': color };
  }
}

vamcs avatar Jun 13 '19 15:06 vamcs