Skip to content

Commit

Permalink
feat(AgmMarkerCluster): add calculator option (#1599)
Browse files Browse the repository at this point in the history
  • Loading branch information
whythecode authored and sebholstein committed Mar 2, 2019
1 parent ba7c97e commit 03ceb1c
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,16 @@ When you import the `AgmJsMarkerClustererModule`, you can use the `agmMarkerClus
<agm-marker *ngFor="let marker of markers" [latitude]="marker.latitude" [longitude]="marker.longitude"></agm-marker>
</agm-marker-cluster>
</agm-map>
```
```

### Specifying a custom calculator

If you want to control how the cluster style is calculated, you can pass in a `CalculateFunction` via `calculator`:

```html
<agm-map [latitude]="0" [longitude]="0">
<agm-marker-cluster [calculator]="myCalculatorFn">
<agm-marker *ngFor="let marker of markers" [latitude]="marker.latitude" [longitude]="marker.longitude"></agm-marker>
</agm-marker-cluster>
</agm-map>
```
10 changes: 9 additions & 1 deletion packages/js-marker-clusterer/directives/marker-cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Directive, Input, OnDestroy, OnChanges, OnInit, SimpleChange} from '@ang
import {ClusterManager} from '../services/managers/cluster-manager';
import {MarkerManager, InfoWindowManager} from '@agm/core';

import {ClusterOptions, ClusterStyle} from '../services/google-clusterer-types';
import {CalculateFunction, ClusterOptions, ClusterStyle} from '../services/google-clusterer-types';

/**
* AgmMarkerCluster clusters map marker if they are near together
Expand Down Expand Up @@ -71,6 +71,11 @@ export class AgmMarkerCluster implements OnDestroy, OnChanges, OnInit, ClusterOp
*/
@Input() styles: ClusterStyle;

/**
* A function that calculates the cluster style and text based on the markers in the cluster.
*/
@Input() calculator: CalculateFunction;

@Input() imagePath: string;
@Input() imageExtension: string;

Expand Down Expand Up @@ -110,6 +115,9 @@ export class AgmMarkerCluster implements OnDestroy, OnChanges, OnInit, ClusterOp
if (changes['imageExtension']) {
this._clusterManager.setImageExtension(this);
}
if (changes['calculator']) {
this._clusterManager.setCalculator(this);
}
}

/** @internal */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {TestBed, async, inject} from '@angular/core/testing';

import {AgmMarker} from '../../../core/directives/marker';
import {GoogleMapsAPIWrapper} from '../../../core/services/google-maps-api-wrapper';
import {Marker} from '../../../core/services/google-maps-types';
import {AgmMarkerCluster} from '../../directives/marker-cluster';
import {ClusterManager} from './cluster-manager';

describe('ClusterManager', () => {
Expand Down Expand Up @@ -207,4 +207,34 @@ describe('ClusterManager', () => {
() => { expect(markerInstance.setZIndex).toHaveBeenCalledWith(zIndex); });
})));
});

describe('set calculator', () => {
it('should call the setCalculator method when the calculator changes and is a function',
inject(
[ClusterManager],
async (markerManager: ClusterManager) => {

const mockClusterer = { setCalculator: jest.fn() };
const instancePromise = Promise.resolve(mockClusterer);

const spy = jest.spyOn(markerManager, 'getClustererInstance')
.mockImplementation(() => instancePromise);

const markerCluster: Partial<AgmMarkerCluster> = {};

// negative case
markerCluster.calculator = null;
markerManager.setCalculator(markerCluster as AgmMarkerCluster);
await instancePromise;
expect(mockClusterer.setCalculator).not.toHaveBeenCalled();

// positive case
markerCluster.calculator = jest.fn();
markerManager.setCalculator(markerCluster as AgmMarkerCluster);
await instancePromise;
expect(mockClusterer.setCalculator).toHaveBeenCalledTimes(1);

spy.mockRestore();
}));
});
});
34 changes: 23 additions & 11 deletions packages/js-marker-clusterer/services/managers/cluster-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ export class ClusterManager extends MarkerManager {
});
}

getClustererInstance(): Promise<MarkerClustererInstance> {
return this._clustererInstance;
}

addMarker(marker: AgmMarker): void {
const clusterPromise: Promise<MarkerClustererInstance> = this._clustererInstance;
const clusterPromise: Promise<MarkerClustererInstance> = this.getClustererInstance();
const markerPromise = this._mapsWrapper
.createMarker({
position: {
Expand Down Expand Up @@ -65,7 +69,7 @@ export class ClusterManager extends MarkerManager {
return m.then((m: Marker) => {
this._zone.run(() => {
m.setMap(null);
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
cluster.removeMarker(m);
this._markers.delete(marker);
});
Expand All @@ -74,66 +78,74 @@ export class ClusterManager extends MarkerManager {
}

clearMarkers(): Promise<void> {
return this._clustererInstance.then(cluster => {
return this.getClustererInstance().then(cluster => {
cluster.clearMarkers();
});
}

setGridSize(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
cluster.setGridSize(c.gridSize);
});
}

setMaxZoom(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
cluster.setMaxZoom(c.maxZoom);
});
}

setStyles(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
cluster.setStyles(c.styles);
});
}

setZoomOnClick(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
if (c.zoomOnClick !== undefined) {
cluster.zoomOnClick_ = c.zoomOnClick;
}
});
}

setAverageCenter(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
if (c.averageCenter !== undefined) {
cluster.averageCenter_ = c.averageCenter;
}
});
}

setImagePath(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
if (c.imagePath !== undefined) {
cluster.imagePath_ = c.imagePath;
}
});
}

setMinimumClusterSize(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
if (c.minimumClusterSize !== undefined) {
cluster.minimumClusterSize_ = c.minimumClusterSize;
}
});
}

setImageExtension(c: AgmMarkerCluster): void {
this._clustererInstance.then(cluster => {
this.getClustererInstance().then(cluster => {
if (c.imageExtension !== undefined) {
cluster.imageExtension_ = c.imageExtension;
}
});
}

setCalculator (c: AgmMarkerCluster): void {
this.getClustererInstance().then(cluster => {
if (typeof c.calculator === 'function') {
cluster.setCalculator(c.calculator);
}
});
}
}

0 comments on commit 03ceb1c

Please sign in to comment.