UNPKG

8.88 kBPlain TextView Raw
1import {AfterContentInit, Directive, EventEmitter, OnChanges, OnDestroy, SimpleChanges} from '@angular/core';
2import {Subscription} from 'rxjs/Subscription';
3
4import {LatLng, LatLngLiteral, PolyMouseEvent, PolygonOptions} from '../services/google-maps-types';
5import {PolygonManager} from '../services/managers/polygon-manager';
6
7/**
8 * SebmGoogleMapPolygon renders a polygon on a {@link SebmGoogleMap}
9 *
10 * ### Example
11 * ```typescript
12 * import { Component } from '@angular/core';
13 * import { SebmGoogleMap, SebmGooglePolygon, LatLngLiteral } from 'angular2-maps/core';
14 *
15 * @Component({
16 * selector: 'my-map-cmp',
17 * styles: [`
18 * .semb-map-container {
19 * height: 300px;
20 * }
21 * `],
22 * template: `
23 * <semb-map [latitude]="lat" [longitude]="lng" [zoom]="zoom">
24 * <semb-map-polygon [paths]="paths">
25 * </semb-map-polygon>
26 * </semb-map>
27 * `
28 * })
29 * export class MyMapCmp {
30 * lat: number = 0;
31 * lng: number = 0;
32 * zoom: number = 10;
33 * paths: Array<LatLngLiteral> = [
34 * { lat: 0, lng: 10 },
35 * { lat: 0, lng: 20 },
36 * { lat: 10, lng: 20 },
37 * { lat: 10, lng: 10 },
38 * { lat: 0, lng: 10 }
39 * ]
40 * // Nesting paths will create a hole where they overlap;
41 * nestedPaths: Array<Array<LatLngLiteral>> = [[
42 * { lat: 0, lng: 10 },
43 * { lat: 0, lng: 20 },
44 * { lat: 10, lng: 20 },
45 * { lat: 10, lng: 10 },
46 * { lat: 0, lng: 10 }
47 * ], [
48 * { lat: 0, lng: 15 },
49 * { lat: 0, lng: 20 },
50 * { lat: 5, lng: 20 },
51 * { lat: 5, lng: 15 },
52 * { lat: 0, lng: 15 }
53 * ]]
54 * }
55 * ```
56 */
57@Directive({
58 selector: 'sebm-map-polygon',
59 inputs: [
60 'clickable',
61 'draggable: polyDraggable',
62 'editable',
63 'fillColor',
64 'fillOpacity',
65 'geodesic',
66 'paths',
67 'strokeColor',
68 'strokeOpacity',
69 'strokeWeight',
70 'visible',
71 'zIndex',
72 ],
73 outputs: [
74 'polyClick', 'polyDblClick', 'polyDrag', 'polyDragEnd', 'polyMouseDown', 'polyMouseMove',
75 'polyMouseOut', 'polyMouseOver', 'polyMouseUp', 'polyRightClick'
76 ]
77})
78export class SebmGoogleMapPolygon implements OnDestroy, OnChanges, AfterContentInit {
79 /**
80 * Indicates whether this Polygon handles mouse events. Defaults to true.
81 */
82 clickable: boolean = true;
83 /**
84 * If set to true, the user can drag this shape over the map. The geodesic
85 * property defines the mode of dragging. Defaults to false.
86 */
87 draggable: boolean = false;
88 /**
89 * If set to true, the user can edit this shape by dragging the control
90 * points shown at the vertices and on each segment. Defaults to false.
91 */
92 editable: boolean = false;
93 /**
94 * The fill color. All CSS3 colors are supported except for extended
95 * named colors.
96 */
97 fillColor: string;
98 /**
99 * The fill opacity between 0.0 and 1.0
100 */
101 fillOpacity: number;
102 /**
103 * When true, edges of the polygon are interpreted as geodesic and will
104 * follow the curvature of the Earth. When false, edges of the polygon are
105 * rendered as straight lines in screen space. Note that the shape of a
106 * geodesic polygon may appear to change when dragged, as the dimensions
107 * are maintained relative to the surface of the earth. Defaults to false.
108 */
109 geodesic: boolean = false;
110 /**
111 * The ordered sequence of coordinates that designates a closed loop.
112 * Unlike polylines, a polygon may consist of one or more paths.
113 * As a result, the paths property may specify one or more arrays of
114 * LatLng coordinates. Paths are closed automatically; do not repeat the
115 * first vertex of the path as the last vertex. Simple polygons may be
116 * defined using a single array of LatLngs. More complex polygons may
117 * specify an array of arrays. Any simple arrays are converted into Arrays.
118 * Inserting or removing LatLngs from the Array will automatically update
119 * the polygon on the map.
120 */
121 paths: Array<LatLng|LatLngLiteral>|Array<Array<LatLng|LatLngLiteral>> = [];
122 /**
123 * The stroke color. All CSS3 colors are supported except for extended
124 * named colors.
125 */
126 strokeColor: string;
127 /**
128 * The stroke opacity between 0.0 and 1.0
129 */
130 strokeOpacity: number;
131 /**
132 * The stroke width in pixels.
133 */
134 strokeWeight: number;
135 /**
136 * Whether this polygon is visible on the map. Defaults to true.
137 */
138 visible: boolean;
139 /**
140 * The zIndex compared to other polys.
141 */
142 zIndex: number;
143
144 /**
145 * This event is fired when the DOM click event is fired on the Polygon.
146 */
147 polyClick: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
148
149 /**
150 * This event is fired when the DOM dblclick event is fired on the Polygon.
151 */
152 polyDblClick: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
153
154 /**
155 * This event is repeatedly fired while the user drags the polygon.
156 */
157 polyDrag: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
158
159 /**
160 * This event is fired when the user stops dragging the polygon.
161 */
162 polyDragEnd: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
163
164 /**
165 * This event is fired when the user starts dragging the polygon.
166 */
167 polyDragStart: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
168
169 /**
170 * This event is fired when the DOM mousedown event is fired on the Polygon.
171 */
172 polyMouseDown: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
173
174 /**
175 * This event is fired when the DOM mousemove event is fired on the Polygon.
176 */
177 polyMouseMove: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
178
179 /**
180 * This event is fired on Polygon mouseout.
181 */
182 polyMouseOut: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
183
184 /**
185 * This event is fired on Polygon mouseover.
186 */
187 polyMouseOver: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
188
189 /**
190 * This event is fired whe the DOM mouseup event is fired on the Polygon
191 */
192 polyMouseUp: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
193
194 /**
195 * This even is fired when the Polygon is right-clicked on.
196 */
197 polyRightClick: EventEmitter<PolyMouseEvent> = new EventEmitter<PolyMouseEvent>();
198
199 private static _polygonOptionsAttributes: Array<string> = [
200 'clickable', 'draggable', 'editable', 'fillColor', 'fillOpacity', 'geodesic', 'icon', 'map',
201 'paths', 'strokeColor', 'strokeOpacity', 'strokeWeight', 'visible', 'zIndex', 'draggable',
202 'editable', 'visible'
203 ];
204
205 private _id: string;
206 private _polygonAddedToManager: boolean = false;
207 private _subscriptions: Subscription[] = [];
208
209 constructor(private _polygonManager: PolygonManager) {}
210
211 /** @internal */
212 ngAfterContentInit() {
213 if (!this._polygonAddedToManager) {
214 this._init();
215 }
216 }
217
218 ngOnChanges(changes: SimpleChanges): any {
219 if (!this._polygonAddedToManager) {
220 this._init();
221 return;
222 }
223
224 this._polygonManager.setPolygonOptions(this, this._updatePolygonOptions(changes));
225 }
226
227 private _init() {
228 this._polygonManager.addPolygon(this);
229 this._polygonAddedToManager = true;
230 this._addEventListeners();
231 }
232
233 private _addEventListeners() {
234 const handlers = [
235 {name: 'click', handler: (ev: PolyMouseEvent) => this.polyClick.emit(ev)},
236 {name: 'dbclick', handler: (ev: PolyMouseEvent) => this.polyDblClick.emit(ev)},
237 {name: 'drag', handler: (ev: MouseEvent) => this.polyDrag.emit(ev)},
238 {name: 'dragend', handler: (ev: MouseEvent) => this.polyDragEnd.emit(ev)},
239 {name: 'dragstart', handler: (ev: MouseEvent) => this.polyDragStart.emit(ev)},
240 {name: 'mousedown', handler: (ev: PolyMouseEvent) => this.polyMouseDown.emit(ev)},
241 {name: 'mousemove', handler: (ev: PolyMouseEvent) => this.polyMouseMove.emit(ev)},
242 {name: 'mouseout', handler: (ev: PolyMouseEvent) => this.polyMouseOut.emit(ev)},
243 {name: 'mouseover', handler: (ev: PolyMouseEvent) => this.polyMouseOver.emit(ev)},
244 {name: 'mouseup', handler: (ev: PolyMouseEvent) => this.polyMouseUp.emit(ev)},
245 {name: 'rightclick', handler: (ev: PolyMouseEvent) => this.polyRightClick.emit(ev)},
246 ];
247 handlers.forEach((obj) => {
248 const os = this._polygonManager.createEventObservable(obj.name, this).subscribe(obj.handler);
249 this._subscriptions.push(os);
250 });
251 }
252
253 private _updatePolygonOptions(changes: SimpleChanges): PolygonOptions {
254 return Object.keys(changes)
255 .filter(k => SebmGoogleMapPolygon._polygonOptionsAttributes.indexOf(k) !== -1)
256 .reduce((obj: any, k: string) => {
257 obj[k] = changes[k].currentValue;
258 return obj;
259 }, {});
260 }
261
262 /** @internal */
263 id(): string { return this._id; }
264
265 /** @internal */
266 ngOnDestroy() {
267 this._polygonManager.deletePolygon(this);
268 // unsubscribe all registered observable subscriptions
269 this._subscriptions.forEach((s) => s.unsubscribe());
270 }
271}