From a87bd6f97e2a7b2d509308db107aab842cfbc3e1 Mon Sep 17 00:00:00 2001 From: Wykks Date: Mon, 21 May 2018 19:15:56 +0200 Subject: [PATCH] feat(markerCluster): expose supercluster by Ouput load event Update demo to use the new way of using markerCluster Supercluster methods as template var is going to be removed in the next major version --- .../marker-cluster.component.ts | 7 +- src/app/showcase/demo/demo.module.ts | 4 +- .../examples/ngx-marker-cluster.component.ts | 94 +++++++++++++++---- .../stackblitz-edit.component.ts | 4 +- src/app/showcase/shared.module.ts | 4 +- src/assets/stackblitz-base.txt | 4 +- 6 files changed, 92 insertions(+), 25 deletions(-) diff --git a/src/app/lib/marker-cluster/marker-cluster.component.ts b/src/app/lib/marker-cluster/marker-cluster.component.ts index 02dda0afd..e15c800d2 100644 --- a/src/app/lib/marker-cluster/marker-cluster.component.ts +++ b/src/app/lib/marker-cluster/marker-cluster.component.ts @@ -11,7 +11,9 @@ import { OnInit, SimpleChanges, TemplateRef, - NgZone + NgZone, + Output, + EventEmitter } from '@angular/core'; import { fromEvent } from 'rxjs/observable/fromEvent'; import { merge } from 'rxjs/observable/merge'; @@ -69,6 +71,8 @@ export class MarkerClusterComponent implements OnChanges, OnDestroy, AfterConten /* Dynamic input */ @Input() data: GeoJSON.FeatureCollection; + @Output() load = new EventEmitter(); + @ContentChild(PointDirective, { read: TemplateRef }) pointTpl: TemplateRef; @ContentChild(ClusterPointDirective, { read: TemplateRef }) clusterPointTpl: TemplateRef; @@ -104,6 +108,7 @@ export class MarkerClusterComponent implements OnChanges, OnDestroy, AfterConten }); this.supercluster = supercluster(options); this.supercluster.load(this.data.features); + this.load.emit(this.supercluster); } ngOnChanges(changes: SimpleChanges) { diff --git a/src/app/showcase/demo/demo.module.ts b/src/app/showcase/demo/demo.module.ts index c130aa35d..654a5b0c2 100644 --- a/src/app/showcase/demo/demo.module.ts +++ b/src/app/showcase/demo/demo.module.ts @@ -32,7 +32,7 @@ import { NgxCustomMarkerIconsComponent } from './examples/ngx-custom-marker-icon import { NgxDragAMarkerComponent } from './examples/ngx-drag-a-marker.component'; import { NgxDragAPointComponent } from './examples/ngx-drag-a-point.component'; import { NgxGeoJSONLineComponent } from './examples/ngx-geojson-line.component'; -import { ClusterPointComponent, NgxMarkerClusterComponent } from './examples/ngx-marker-cluster.component'; +import { ClusterPopupComponent, NgxMarkerClusterComponent } from './examples/ngx-marker-cluster.component'; import { NgxScaleControlComponent } from './examples/ngx-scale-control.component'; import { PopupOnClickComponent } from './examples/popup-on-click.component'; import { PopupComponent } from './examples/popup.component'; @@ -144,7 +144,7 @@ export const DEMO_ROUTES: Routes = [ PopupOnClickComponent, ZoomtoLinestringComponent, NgxMarkerClusterComponent, - ClusterPointComponent, + ClusterPopupComponent, Display3dBuildingsComponent ] }) diff --git a/src/app/showcase/demo/examples/ngx-marker-cluster.component.ts b/src/app/showcase/demo/examples/ngx-marker-cluster.component.ts index 8e6ac6dc3..d91377d14 100644 --- a/src/app/showcase/demo/examples/ngx-marker-cluster.component.ts +++ b/src/app/showcase/demo/examples/ngx-marker-cluster.component.ts @@ -1,25 +1,49 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; +import { MatPaginator, PageEvent } from '@angular/material'; +import { LngLatLike } from 'mapbox-gl'; +import { Cluster, Supercluster } from 'supercluster'; @Component({ // tslint:disable-next-line:component-selector - selector: 'demo-cluster-point', + selector: 'demo-cluster-popup', template: ` -
- {{ feature.properties?.point_count }} -
- ` + + + {{ leaf.properties['Primary ID'] }} + + + + ` }) -export class ClusterPointComponent { - @Input() feature: GeoJSON.Feature; - @Input() getLeavesFn: (limit?: number, offset?: number) => GeoJSON.Feature[]; - @Input() getClusterExpansionZoomFn: () => number; - - alert() { - const clusters = this.getLeavesFn(); - let message = 'childs: '; - message += clusters.map((cluster) => cluster.properties!['Primary ID']).join(', '); - message += ` getClusterExpansionZoom(): ${this.getClusterExpansionZoomFn()}`; - alert(message); +export class ClusterPopupComponent implements OnChanges { + @Input() clusterId: GeoJSON.Feature; + @Input() supercluster: Supercluster; + @Input() count: number; + + @ViewChild(MatPaginator) paginator: MatPaginator; + + leaves: GeoJSON.Feature[]; + + ngOnChanges(changes: SimpleChanges) { + this.changePage(); + if (changes.count && !changes.count.isFirstChange()) { + this.paginator.firstPage(); + } + } + + changePage(pageEvent?: PageEvent) { + let offset = 0; + if (pageEvent) { + offset = pageEvent.pageIndex * 5; + } + // Typing issue in supercluster + this.leaves = (this.supercluster.getLeaves)(this.clusterId, 5, offset); } } @@ -36,6 +60,7 @@ export class ClusterPointComponent { [data]="earthquakes" [maxZoom]="14" [radius]="50" + (load)="supercluster = $event" >
- - + +
+ {{ feature.properties?.point_count }} +
+ + + `, styleUrls: ['./examples.css', './ngx-marker-cluster.component.css'] }) export class NgxMarkerClusterComponent implements OnInit { earthquakes: object; + supercluster: Supercluster; + selectedCluster: { + lngLat: LngLatLike; + count: number; + id: number; + }; async ngOnInit() { this.earthquakes = await import('./earthquakes.geo.json'); } + + selectCluster(event: MouseEvent, feature: Cluster) { + event.stopPropagation(); // This is needed, otherwise the popup will close immediately + this.selectedCluster = { + // Change the ref, to trigger mgl-popup onChanges (when the user click on the same cluster) + lngLat: [ ...feature.geometry!.coordinates ], + count: feature.properties.point_count!, + id: feature.properties.cluster_id! + }; + } } diff --git a/src/app/showcase/demo/stackblitz-edit/stackblitz-edit.component.ts b/src/app/showcase/demo/stackblitz-edit/stackblitz-edit.component.ts index 4eeea9237..41dc11c7d 100644 --- a/src/app/showcase/demo/stackblitz-edit/stackblitz-edit.component.ts +++ b/src/app/showcase/demo/stackblitz-edit/stackblitz-edit.component.ts @@ -155,7 +155,9 @@ margin: 0; '@angular/forms': '*', 'url': '*', 'querystring': '*', - '@types/mapbox-gl': '*' + 'rxjs-compat': '*', + '@types/mapbox-gl': '*', + '@types/supercluster': '*' } }; await this.zone.runOutsideAngular(async () => { diff --git a/src/app/showcase/shared.module.ts b/src/app/showcase/shared.module.ts index 7cf6ac04c..a53fb57c3 100644 --- a/src/app/showcase/shared.module.ts +++ b/src/app/showcase/shared.module.ts @@ -13,7 +13,8 @@ import { MatRadioModule, MatSidenavModule, MatSlideToggleModule, - MatToolbarModule + MatToolbarModule, + MatPaginatorModule } from '@angular/material'; import { NgxMapboxGLModule } from '../lib'; @@ -31,6 +32,7 @@ const Modules = [ MatInputModule, MatIconModule, MatSidenavModule, + MatPaginatorModule, FormsModule, NgxMapboxGLModule ]; diff --git a/src/assets/stackblitz-base.txt b/src/assets/stackblitz-base.txt index dafa3a751..e2335cb21 100644 --- a/src/assets/stackblitz-base.txt +++ b/src/assets/stackblitz-base.txt @@ -12,7 +12,8 @@ import { MatProgressSpinnerModule, MatRadioModule, MatSlideToggleModule, - MatToolbarModule + MatToolbarModule, + MatPaginatorModule } from '@angular/material'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @@ -33,6 +34,7 @@ const demoArray = Object.values(demo); MatCardModule, MatSlideToggleModule, MatProgressSpinnerModule, + MatPaginatorModule, NgxMapboxGLModule.forRoot({ accessToken: 'pk.eyJ1Ijoid3lra3NzIiwiYSI6ImNqMjR6aTdmdzAwNHMzMnBvbjBucjlqNm8ifQ.6GjGpofWBVaIuSnhdXQb5w' })