Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clustered markers #1044

Closed
wants to merge 10 commits into from
Closed

Conversation

jigfox
Copy link
Contributor

@jigfox jigfox commented Jun 12, 2017

This adds a new directive <agm-cluster> which allows to group markers into clusters if they are near each other like described and requested in #307. It uses the https://github.com/googlemaps/js-marker-clusterer to achieve this goal.

Copy link

@hismethod hismethod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a Good Feature what I want!!!!

Copy link
Owner

@sebholstein sebholstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jigfox wow, thank you, this looks really good!

One note: I would like to keep the @agm/core package as a place for core Google Maps API features, so this package has no other external dependencies (like js-marker-clusterer).

We need to think about how we can structure this repo so that we can host multiple packages (like in the official angular repo).

I would propose the following package name: @agm/js-marker-clusterer

selector: 'agm-cluster',
providers: [ClusterManager, {provide: MarkerManager, useExisting: ClusterManager}]
})
export class AgmCluster implements OnDestroy, OnChanges, OnInit {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgmMarkerCluster

providers: [ClusterManager, {provide: MarkerManager, useExisting: ClusterManager}]
})
export class AgmCluster implements OnDestroy, OnChanges, OnInit {
@Input() gridSize: number;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a description for the inputs and outputs?

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

constructor(private cluster: ClusterManager) {}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private _markerClusterManager: MarkerClusterManager

import {Marker} from '../google-maps-types';

@Injectable()
export class ClusterManager extends MarkerManager {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MarkerClusterManager

});
}

init(options:{}) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a concrete type here for options?

package.json Outdated
@@ -44,7 +44,8 @@
"homepage": "https://angular-maps.com",
"peerDependencies": {
"@angular/common": "^4.0.0 || ^2.0.0",
"@angular/core": "^4.0.0 || ^2.0.0"
"@angular/core": "^4.0.0 || ^2.0.0",
"js-marker-clusterer": "^1.0.0"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have a separate @agm package to handle the different dependencies. (See my last comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be possible, what name would you suggest? I will try with @agm/cluster, if this is okay with you

@@ -547,13 +547,13 @@ export interface CalculatorResult {

export type CalculateFunction = (marker: Marker[], count: number) => CalculatorResult;

export interface MarkerClusterer {
export interface IMarkerClusterer {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MarklerClusterer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That ist not that easy because tslint doesn't like it. The js-marker-clusterer package will create a global var called MarkerClusterer, which I have to declare src/core/services/managers/cluster-manager.ts:12

@@ -7,9 +7,9 @@ import {GoogleMapsAPIWrapper} from './../google-maps-api-wrapper';
import {AgmMarker} from './../../directives/marker';
import {AgmCluster} from './../../directives/cluster';
// tslint:disable-next-line: no-use-before-declare
import {Marker, MarkerClusterer, IClusterOptions} from '../google-maps-types';
import {Marker, IMarkerClusterer, IClusterOptions} from '../google-maps-types';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClusterOptions

imageExtension_:string;
}

export interface IClusterOptions {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClusterOptions

@jigfox
Copy link
Contributor Author

jigfox commented Jun 12, 2017

Hi, thanks for your Feedback. What name would you suggest your message seems like it was cut off:

I would propose the following package name:

I will Change all other things like requested

@sebholstein
Copy link
Owner

sebholstein commented Jun 18, 2017

@jigfox oh yeah, missed that. I would propose "@ agm/js-marker-clusterer".

So in the src folder, we would have another folder @ agm/js-marker-clusterer and we would rename the core folder to @ agm/core.

Please let me know when the changes are done. Thank you!

@jigfox jigfox changed the title Add clustered markers WIP: Add clustered markers Jun 20, 2017
@jigfox
Copy link
Contributor Author

jigfox commented Jun 20, 2017

@SebastianM I have some trouble with dependencies while splitting the cluster into its own module: https://github.com/inovex/angular-google-maps/pull/1/files

So I need some help here, integrating this. Another much simpler option would be to create a completely new repo for the clusterer. It would not be the same as in angular itself, but it would be easier to maintain. What do you think?

@sebholstein
Copy link
Owner

@jigfox thx. I worked on a multi-package solution yesterday in this PR (#1051) to support Snazzy Info Window. It's nearly done - I will merge this tomorrow. Afterwards, I can do the package modifications or you can also do this if you want to.

The important part is that the manager cannot be in the providers array of the AgmMap class, so we need a solution for this.

@sebholstein
Copy link
Owner

@jigfox #1051 is merged. There should be everything you need to create another package. Let me know if there are any questions.

@jigfox
Copy link
Contributor Author

jigfox commented Jun 22, 2017

okay, I will try this approach, thank you

@jigfox jigfox force-pushed the add-clustered-markers branch from a58dba2 to 28c05ea Compare June 22, 2017 13:15
@jigfox jigfox changed the title WIP: Add clustered markers Add clustered markers Jun 23, 2017
@jigfox
Copy link
Contributor Author

jigfox commented Jun 26, 2017

@SebastianM: I have created a new package like the already existing. Is this okay, the way it is? Or should I change something?

@sebholstein
Copy link
Owner

@jigfox thx. I will review it tomorrow.

@ekaitzht
Copy link

Any time planing to merge this to master? Thanks

@nelsonBlack
Copy link

Also patiently waiting for the merge to be done

@reginbald
Copy link

reginbald commented Jul 11, 2017

@SebastianM When do you think this will be merged and released?

@jigfox
Copy link
Contributor Author

jigfox commented Aug 23, 2017

@SebastianM Congrats, I totally understand

@quedicesebas
Copy link
Contributor

Please, a demo of this? and complete docs

@pauljosephatay
Copy link

@sebrojas14, I believe you can follow the snazzy window guide

  1. npm install js-marker-clusterer @agm/js-marker-clusterer
  • depends on js-marker-clusterer
  1. import the module
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

// add these imports
import { AgmCoreModule } from '@agm/core';
import { AgmJsMarkerClustererModule } from '@agm/js-marker-clusterer';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AgmCoreModule.forRoot({
      apiKey: ['YOUR_API_KEY_HERE']
    }),
    AgmJsMarkerClustererModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  1. is should be available in the template, note the selector is agm-marker-cluster as of beta1
<agm-map style="height: 300px" [latitude]="51.673858" [longitude]="7.815982">
  <agm-marker-cluster
  imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
    <agm-marker [latitude]="51.673858" [longitude]="7.815982">
    </agm-marker><!-- multiple markers -->
  </agm-marker-cluster>
</agm-map>

@jigfox
Copy link
Contributor Author

jigfox commented Sep 1, 2017

thanks @pauljosephatay I took your example Code and put it into the README

@jigfox jigfox deleted the add-clustered-markers branch September 1, 2017 05:25
@sadeajayi
Copy link

On compilation im getting
EXCEPTION: Uncaught (in promise): Error: Error in ./MapPageComponent class MapPageComponent - inline template:19:12 caused by: No provider for GoogleMapsAPIWrapper!

@kuncevic kuncevic mentioned this pull request Sep 4, 2017
@kuncevic
Copy link

kuncevic commented Sep 4, 2017

@pauljosephatay getting error as mentioned here #1124 (comment) any thoughts?

@sadeajayi
Copy link

What i'm basically trying to do is add markers on clicking the map, and clustering them in real time, i don't even know if logically speaking, this feature is possible?

@pauljosephatay
Copy link

@kuncevic probably dependency with js-marker-clusterer. please check out README installation and usage
npm install js-marker-clusterer @agm/js-marker-clusterer --save
or
yarn add js-marker-clusterer @agm/js-marker-clusterer

@sadeajayi, i believe no special treatment needed, like this

template:
<agm-map style="height: 300px" [latitude]="51.673858" [longitude]="7.815982"
  (mapClick)="addMarker($event)">
  <agm-marker-cluster
  imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
    <agm-marker *ngFor="let marker of markers"
      [latitude]="marker.lat"
      [longitude]="marker.lng">
    </agm-marker>
  </agm-marker-cluster>
</agm-map>

=============
component:

markers = [];

addMarker($event){
this.markers.push($event.coords);
}

@kuncevic
Copy link

kuncevic commented Sep 4, 2017

@pauljosephatay I done the install thing as I pinted in comment I can see the files listed in my node_modules . Also I tried to just reinstall the whole node_modules and getting caught by the same error.

image

image

image

My env:

@angular/cli: 1.3.2
node: 7.8.0
os: win32 x64
@angular/animations: 4.3.5

html:

<agm-map style="height: 300px" [latitude]=lat [longitude]=lng>
  <agm-marker-cluster [imagePath]="'https://googlemaps.github.io/js-marker-clusterer/images/m'">
    <agm-marker *ngFor="let marker of markers" [latitude]="marker.lat" [longitude]="marker.lng"></agm-marker>
  </agm-marker-cluster>
</agm-map>

app.module

import { AgmCoreModule } from '@agm/core';
import { AgmJsMarkerClustererModule, ClusterManager } from '@agm/js-marker-clusterer';

@NgModule({
  declarations: [
    AppComponent,
    MapsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AgmCoreModule.forRoot({
      apiKey: 'key'
    }),
    AgmJsMarkerClustererModule
  ],
  providers: [
    ClusterManager
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

@pauljosephatay
Copy link

@kuncevic sorry, i guess if you already installed both 1) js-marker-clusterer and 2) @agm/js-marker-clusterer then im not sure what could be the problem. you may create a new clean app with ng cli and install agm map then follow the README and see if it works.

@kuncevic
Copy link

kuncevic commented Sep 4, 2017

@pauljosephatay all good now. I was actually missing the js-marker-clusterer module. Thanks for help.

@sadeajayi
Copy link

@kuncevic how did you include the js-marker-clusterer module in the app module?

@sadeajayi
Copy link

im still getting
On compilation im getting
EXCEPTION: Uncaught (in promise): Error: Error in ./MapPageComponent class MapPageComponent - inline template:19:12 caused by: No provider for GoogleMapsAPIWrapper!

error on compilation even after including the wrapper as a provider and importing that.
This is what i have

The imports im making in my map-page.component.ts

import { Component, NgModule, NgZone, OnInit, ViewChild, ElementRef } from '@angular/core';
import {MarkerService} from "../../services/marker.service";

import { AgmCoreModule, MapsAPILoader } from 'angular2-google-maps/core';
import { FormControl, FormsModule, ReactiveFormsModule } from "@angular/forms";
import { MapCluster } from '../../map-cluster';
import { AgmJsMarkerClustererModule } from "@agm/js-marker-clusterer";

import 'js-marker-clusterer/src/markerclusterer.js';

import {Http, HttpModule} from '@angular/http';

//Importing socket-io services for real-time interactions
import { SocketService } from '../shared/socket.service';
import {GoogleMapsAPIWrapper} from "angular2-google-maps/core/services/google-maps-api-wrapper";

Imports in my app module.ts

import {  AgmCoreModule, MapsAPILoader } from "angular2-google-maps/core";
import { AgmJsMarkerClustererModule } from "@agm/js-marker-clusterer";
import { MapCluster } from './map-cluster';

import {GoogleMapsAPIWrapper} from "angular2-google-maps/core/services/google-maps-api-wrapper";

import { AppComponent } from './app.component';
import { MapPageComponent } from './components/map-page/map-page.component';
import 'js-marker-clusterer/src/markerclusterer.js';

imports: [
    BrowserModule,
    FormsModule,
    FacebookModule.forRoot(),
    AgmCoreModule.forRoot({
      apiKey: 'AIzaSyBfW8ETNs6vnLAlGqcqHIZg52NI9lupHxM',
      libraries: ["places"]
    }),
    AgmJsMarkerClustererModule,
  ],
  providers: [ValidateService, MarkerService, SocketService, GoogleMapsAPIWrapper],

@kuncevic
Copy link

kuncevic commented Sep 4, 2017

@sadeajayi check my app.module code just in a comment above

But you have an issue with GoogleMapsAPIWrapper you need to provide that thing.
Also why you are mixing angular2-google-maps (old) and @agm (new) modules? check the docs.

@sadeajayi
Copy link

Oh okay, I did just that and im still getting the same errors

@kuncevic
Copy link

kuncevic commented Sep 4, 2017

@sadeajayi are you importing GoogleMapsAPIWrapper from @agm/core like:

import { GoogleMapsAPIWrapper } from '@agm/core';

@sadeajayi
Copy link

@kuncevic Oh my God. Youre a life saver.
This whole time i was importing my googlemapsAPI wrapper with the
"angular2-google-maps/core" module i installed 2 months ago instead of using @agm/core.
I was importing agmCoreModule and MapsAPILoader with that same module as well.
I was wondering what was causing my bugs for the last 3 weeks and I couldn't understand what was wrong.
Thanks man

@BayardSmart
Copy link

Hi, I have this error when trying to compile : ERROR in C:/....../node_modules/@agm/js-marker-clusterer/services/managers/cluster-manager.d.ts (8,22): Class 'ClusterManager' incorrectly extends base class 'MarkerManager'.
Property '_mapsWrapper' is private in type 'MarkerManager' but not in type 'ClusterManager'.

Any Idea ?

@MarKco
Copy link

MarKco commented Sep 8, 2017

I'm experiencing the same issue: added the library following the readme instructions and can't compile because of the following

ERROR in C:/.../node_modules/@agm/js-marker-clusterer/services/managers/cluster-manager.d.ts (8,22): Class 'ClusterManager' incorrectly extends base class 'MarkerManager'. Property '_mapsWrapper' is private in type 'MarkerManager' but not in type 'ClusterManager'.

@jigfox
Copy link
Contributor Author

jigfox commented Sep 8, 2017

@uakgul-talis @MarKco
which version of @agm/core are you running? It should be working in 1.0.0-beta.1 as you can see here the property _mapsWrapper isn't private but protected as it should be: https://github.com/SebastianM/angular-google-maps/blob/c16295d331cbb74841585cf433ab7af3d7e415d5/packages/core/services/managers/marker-manager.ts#L15

@MarKco
Copy link

MarKco commented Sep 8, 2017

I installed with npm install js-marker-clusterer @agm/js-marker-clusterer --save, in the installation log I see the following: @agm/[email protected]

So it seems I'm already running the beta.1. Any chance the change was not deployed?

@jigfox
Copy link
Contributor Author

jigfox commented Sep 8, 2017

@agm/[email protected] is not the same as @agm/[email protected] what version of @agm/core are you running?

@MarKco
Copy link

MarKco commented Sep 8, 2017

You were right!
Since I had agm/core installed for a long time it wasn't updated. I performed an npm update , version @agm/[email protected] was installed and now clustering works as expected! :)

I guess this could probably be the way to solve the issue for @uakgul-talis as well! Thank you!

@BayardSmart
Copy link

@jigfox Thanks man !!! It's working properly now.
I also performed a npm update like @MarKco did .

Thank you again!

@sadeajayi
Copy link

Hi guys, I have another issue
I'm trying to write a method in my component.ts file to handle deletion of markers.
Basically, if a user drops a marker at location 'x', but moves out of a set radius for that location, their marker should get deleted.
So if there's a cluster showing 45 markers at a location, and one user leaves that location, the number of markers will reduce by 1.
I just don't know how to go about implementing deletion in my component.ts file please help

srwebdev3627 added a commit to srwebdev3627/angular-google-maps that referenced this pull request Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.