-
Notifications
You must be signed in to change notification settings - Fork 817
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(*): add clustered markers support
Closes #1044
- Loading branch information
1 parent
dd9a087
commit 5cbc515
Showing
19 changed files
with
1,276 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"name": "@agm/dummy", | ||
"name": "@agm/_dev", | ||
"private": true, | ||
"version": "1.0.0-beta.0", | ||
"description": "Angular 2+ components for Google Maps", | ||
|
@@ -25,8 +25,9 @@ | |
"packagejson": "node ./scripts/create-package-json.js", | ||
"copyassets": "node ./scripts/copy-package-assets.js", | ||
"scripts": "npm run ngc:esm && npm run bundle", | ||
"bundle": "npm run bundle:umd:core", | ||
"bundle": "npm run bundle:umd:core && npm run bundle:umd:jsmarkerclusterer", | ||
"bundle:umd:core": "rollup -c rollup.core.config.js", | ||
"bundle:umd:jsmarkerclusterer": "rollup -c rollup.js-marker-clusterer.config.js", | ||
"ngc:esm": "ngc -p tsconfig.json", | ||
"clang:format": "clang-format --glob=packages/**/*.ts -i", | ||
"postngc:esm": "mkdir -p dist/ && cp -R .tmp/esm/* dist/ && rimraf packages/**/*.ngfactory.ts", | ||
|
@@ -35,9 +36,10 @@ | |
"ci": "npm run build && npm run test", | ||
"docs:clean": "rimraf docs/public", | ||
"docs:hugo": "cd docs && hugo", | ||
"docs": "npm run docs:hugo && npm run apidocs:core && npm run apidocs:snazzy", | ||
"docs": "npm run docs:hugo && npm run apidocs:core && npm run apidocs:snazzy && npm run apidocs:jsmarkerclusterer", | ||
"apidocs:core": "compodoc -p packages/core/tsconfig.compodoc.json --name @agm/core --output docs/public/api-docs/agm-core/ --disablePrivateOrInternalSupport --hideGenerator --disableCoverage", | ||
"apidocs:snazzy": "compodoc -p packages/snazzy-info-window/tsconfig.compodoc.json --name @agm/snazzy-info-window --output docs/public/api-docs/agm-snazzy-info-window/ --disablePrivateOrInternalSupport --hideGenerator --disableCoverage" | ||
"apidocs:snazzy": "compodoc -p packages/snazzy-info-window/tsconfig.compodoc.json --name @agm/snazzy-info-window --output docs/public/api-docs/agm-snazzy-info-window/ --disablePrivateOrInternalSupport --hideGenerator --disableCoverage", | ||
"apidocs:jsmarkerclusterer": "compodoc -p packages/js-marker-clusterer/tsconfig.compodoc.json --name @agm/js-marker-clusterer --output docs/public/api-docs/js-marker-clusterer/ --disablePrivateOrInternalSupport --hideGenerator --disableCoverage" | ||
}, | ||
"author": "Sebastian Müller <[email protected]>", | ||
"license": "MIT", | ||
|
@@ -73,6 +75,7 @@ | |
"html-webpack-plugin": "^2.8.1", | ||
"istanbul-instrumenter-loader": "^2.0.0", | ||
"jasmine-core": "2.5.0", | ||
"js-marker-clusterer": "^1.0.0", | ||
"karma": "^1.3.0", | ||
"karma-chrome-launcher": "2.0.0", | ||
"karma-coverage": "^1.1.1", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {AgmMarkerCluster} from './directives/marker-cluster'; |
124 changes: 124 additions & 0 deletions
124
packages/js-marker-clusterer/directives/marker-cluster.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import {Directive, Input, OnDestroy, OnChanges, OnInit, SimpleChange} from '@angular/core'; | ||
|
||
import {ClusterManager} from '../services/managers/cluster-manager'; | ||
import {MarkerManager} from '@agm/core'; | ||
|
||
import {ClusterOptions, ClusterStyle} from '../services/google-clusterer-types'; | ||
|
||
/** | ||
* AgmMarkerCluster clusters map marker if they are near together | ||
* | ||
* ### Example | ||
* ```typescript | ||
* import { Component } from '@angular/core'; | ||
* | ||
* @Component({ | ||
* selector: 'my-map-cmp', | ||
* styles: [` | ||
* agm-map { | ||
* height: 300px; | ||
* } | ||
* `], | ||
* template: ` | ||
* <agm-map [latitude]="lat" [longitude]="lng" [zoom]="zoom"> | ||
* <agm-marker-cluster> | ||
* <agm-marker [latitude]="lat" [longitude]="lng" [label]="'M'"> | ||
* </agm-marker> | ||
* <agm-marker [latitude]="lat2" [longitude]="lng2" [label]="'N'"> | ||
* </agm-marker> | ||
* </agm-marker-cluster> | ||
* </agm-map> | ||
* ` | ||
* }) | ||
* ``` | ||
*/ | ||
@Directive({ | ||
selector: 'agm-marker-cluster', | ||
providers: [ClusterManager, {provide: MarkerManager, useExisting: ClusterManager}] | ||
}) | ||
export class AgmMarkerCluster implements OnDestroy, OnChanges, OnInit, ClusterOptions { | ||
/** | ||
* The grid size of a cluster in pixels | ||
*/ | ||
@Input() gridSize: number; | ||
|
||
/** | ||
* The maximum zoom level that a marker can be part of a cluster. | ||
*/ | ||
@Input() maxZoom: number; | ||
|
||
/** | ||
* Whether the default behaviour of clicking on a cluster is to zoom into it. | ||
*/ | ||
@Input() zoomOnClick: boolean; | ||
|
||
/** | ||
* Whether the center of each cluster should be the average of all markers in the cluster. | ||
*/ | ||
@Input() averageCenter: boolean; | ||
|
||
/** | ||
* The minimum number of markers to be in a cluster before the markers are hidden and a count is shown. | ||
*/ | ||
@Input() minimumClusterSize: number; | ||
|
||
/** | ||
* An object that has style properties. | ||
*/ | ||
@Input() styles: ClusterStyle; | ||
|
||
@Input() imagePath: string; | ||
@Input() imageExtension: string; | ||
|
||
constructor(private _clusterManager: ClusterManager) {} | ||
|
||
/** @internal */ | ||
ngOnDestroy() { | ||
this._clusterManager.clearMarkers(); | ||
} | ||
|
||
/** @internal */ | ||
ngOnChanges(changes: {[key: string]: SimpleChange }) { | ||
if (changes['gridSize']) { | ||
this._clusterManager.setGridSize(this); | ||
} | ||
if (changes['maxZoom']) { | ||
this._clusterManager.setMaxZoom(this); | ||
} | ||
if (changes['styles']) { | ||
this._clusterManager.setStyles(this); | ||
} | ||
if (changes['zoomOnClick']) { | ||
this._clusterManager.setZoomOnClick(this); | ||
} | ||
if (changes['averageCenter']) { | ||
this._clusterManager.setAverageCenter(this); | ||
} | ||
if (changes['minimumClusterSize']) { | ||
this._clusterManager.setMinimumClusterSize(this); | ||
} | ||
if (changes['styles']) { | ||
this._clusterManager.setStyles(this); | ||
} | ||
if (changes['imagePath']) { | ||
this._clusterManager.setImagePath(this); | ||
} | ||
if (changes['imageExtension']) { | ||
this._clusterManager.setImageExtension(this); | ||
} | ||
} | ||
|
||
/** @internal */ | ||
ngOnInit() { | ||
this._clusterManager.init({ | ||
gridSize: this.gridSize, | ||
maxZoom: this.maxZoom, | ||
zoomOnClick: this.zoomOnClick, | ||
averageCenter: this.averageCenter, | ||
minimumClusterSize: this.minimumClusterSize, | ||
styles: this.styles, | ||
imagePath: this.imagePath, | ||
imageExtension: this.imageExtension, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// main modules | ||
export * from './directives'; | ||
export * from './services'; | ||
|
||
// we explicitly export the module here to prevent this Ionic 2 bug: | ||
// http://stevemichelotti.com/integrate-angular-2-google-maps-into-ionic-2/ | ||
export { AgmJsMarkerClustererModule } from './js-marker-clusterer.module'; |
11 changes: 11 additions & 0 deletions
11
packages/js-marker-clusterer/js-marker-clusterer.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {NgModule} from '@angular/core'; | ||
import {AgmCoreModule} from '@agm/core'; | ||
import {AgmMarkerCluster} from './directives/marker-cluster'; | ||
|
||
@NgModule({ | ||
imports: [AgmCoreModule], | ||
declarations: [AgmMarkerCluster], | ||
exports: [AgmMarkerCluster] | ||
}) | ||
export class AgmJsMarkerClustererModule { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "@agm/clusterer-src", | ||
"dependencies": { | ||
"@agm/core": "file:../core" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@agm/js-marker-clusterer", | ||
"version": "INSERT_HERE_VIA_BUILD_PROCESS", | ||
"private": true, | ||
"description": "Angular Google Maps (AGM) extension for js-marker-clusterer support", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/SebastianM/angular-google-maps.git" | ||
}, | ||
"keywords": [ | ||
"angular-google-maps", | ||
"angular", | ||
"js-marker-clusterer", | ||
"google-maps", | ||
"agm" | ||
], | ||
"author": "Jens Fahnenbruck <[email protected]>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/SebastianM/angular-google-maps/issues" | ||
}, | ||
"peerDependencies": { | ||
"@angular/core": "^4.0.0", | ||
"@agm/core": "^1.0.0-beta.0", | ||
"js-marker-clusterer": "^1.0.0" | ||
}, | ||
"homepage": "https://github.com/SebastianM/angular-google-maps#readme" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {ClusterManager} from './services/managers/cluster-manager'; |
114 changes: 114 additions & 0 deletions
114
packages/js-marker-clusterer/services/google-clusterer-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import {Marker, GoogleMap, LatLngBounds} from '@agm/core/services/google-maps-types'; | ||
|
||
export interface CalculatorResult { | ||
text: string; | ||
index: number; | ||
} | ||
|
||
export type CalculateFunction = (marker: Marker[], count: number) => CalculatorResult; | ||
|
||
export interface MarkerClustererInstance { | ||
zoomOnClick_: boolean; | ||
averageCenter_: boolean; | ||
imagePath_: string; | ||
minimumClusterSize_: number; | ||
imageExtension_: string; | ||
new(map: GoogleMap, marker: Marker[], options: ClusterOptions): MarkerClustererInstance; | ||
addMarker(marker: Marker, noDraw?: boolean): void; | ||
addMarkers(markers: Marker[], noDraw?: boolean): void; | ||
clearMarkers(): void; | ||
getCalculator(): CalculateFunction; | ||
getExtendedBounds(bounds: LatLngBounds): LatLngBounds; | ||
getGridSize(): number; | ||
getMap(): GoogleMap; | ||
getMarkers(): Marker[]; | ||
getStyles(): ClusterStyle; | ||
getTotalClusters(): number; | ||
getTotalMarkers(): Marker[]; | ||
isZoomOnClick(): boolean; | ||
redraw(): void; | ||
removeMarker(marker: Marker): boolean; | ||
resetViewport(): void; | ||
setCalculator(calculator: CalculateFunction): void; | ||
setGridSize(size: number): void; | ||
setMap(map: GoogleMap): void; | ||
setMaxZoom(maxZoom: number): void; | ||
setStyles(styles: ClusterStyle): void; | ||
} | ||
|
||
export interface ClusterOptions { | ||
/** | ||
* The grid size of a cluster in pixels. | ||
*/ | ||
gridSize?: number; | ||
|
||
/** | ||
* The maximum zoom level that a marker can be part of a cluster. | ||
*/ | ||
maxZoom?: number; | ||
|
||
/** | ||
* Whether the default behaviour of clicking on a cluster is to zoom into it. | ||
*/ | ||
zoomOnClick?: boolean; | ||
|
||
/** | ||
* Whether the center of each cluster should be the average of all markers in the cluster. | ||
*/ | ||
averageCenter?: boolean; | ||
|
||
/** | ||
* The minimum number of markers to be in a cluster before the markers are hidden and a count is shown. | ||
*/ | ||
minimumClusterSize?: number; | ||
|
||
/** | ||
* An object that has style properties. | ||
*/ | ||
styles?: ClusterStyle; | ||
|
||
imagePath?: string; | ||
imageExtension?: string; | ||
} | ||
|
||
export interface ClusterStyle { | ||
/** | ||
* The image url. | ||
*/ | ||
url?: string; | ||
|
||
/** | ||
* The image height. | ||
*/ | ||
height?: number; | ||
|
||
/** | ||
* The image width. | ||
*/ | ||
width?: number; | ||
|
||
/** | ||
* The anchor position of the label text. | ||
*/ | ||
anchor?: [number, number]; | ||
|
||
/** | ||
* The text color. | ||
*/ | ||
textColor?: string; | ||
|
||
/** | ||
* The text size. | ||
*/ | ||
textSize?: number; | ||
|
||
/** | ||
* The position of the backgound x, y. | ||
*/ | ||
backgroundPosition?: string; | ||
|
||
/** | ||
* The anchor position of the icon x, y. | ||
*/ | ||
iconAnchor?: [number, number]; | ||
} |
Oops, something went wrong.