Skip to content
This repository was archived by the owner on Jun 23, 2025. It is now read-only.

Commit 46a39b7

Browse files
authored
feat(Polyline): add IconSequences to Polylines
add icon sequences to AgmPolyline as child directives fixes #721
1 parent 75bcfa0 commit 46a39b7

9 files changed

Lines changed: 437 additions & 35 deletions

File tree

packages/core/core.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {LAZY_MAPS_API_CONFIG, LazyMapsAPILoaderConfigLiteral} from './services/m
1414
import {MapsAPILoader} from './services/maps-api-loader/maps-api-loader';
1515
import {BROWSER_GLOBALS_PROVIDERS} from './utils/browser-globals';
1616
import {AgmFitBounds} from './directives/fit-bounds';
17+
import { AgmPolylineIcon } from './directives/polyline-icon';
1718

1819
/**
1920
* @internal
@@ -22,7 +23,7 @@ export function coreDirectives() {
2223
return [
2324
AgmMap, AgmMarker, AgmInfoWindow, AgmCircle, AgmRectangle,
2425
AgmPolygon, AgmPolyline, AgmPolylinePoint, AgmKmlLayer,
25-
AgmDataLayer, AgmFitBounds
26+
AgmDataLayer, AgmFitBounds, AgmPolylineIcon
2627
];
2728
}
2829

packages/core/directives.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export {AgmPolygon} from './directives/polygon';
99
export {AgmPolyline} from './directives/polyline';
1010
export {AgmPolylinePoint} from './directives/polyline-point';
1111
export {AgmFitBounds} from './directives/fit-bounds';
12+
export {AgmPolylineIcon} from './directives/polyline-icon';
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { Directive, Input, OnInit } from '@angular/core';
2+
import { SymbolPath } from '../services/google-maps-types';
3+
4+
/**
5+
* AgmPolylineIcon enables to add polyline sequences to add arrows, circle,
6+
* or custom icons either along the entire line, or in a specific part of it.
7+
* See https://developers.google.com/maps/documentation/javascript/shapes#polyline_customize
8+
*
9+
* ### Example
10+
* ```html
11+
* <agm-map [latitude]="lat" [longitude]="lng" [zoom]="zoom">
12+
* <agm-polyline>
13+
* <agm-icon-sequence [fixedRotation]="true" [path]="'FORWARD_OPEN_ARROW'">
14+
* </agm-icon-sequence>
15+
* </agm-polyline>
16+
* </agm-map>
17+
* ```
18+
*
19+
* @export
20+
* @class AgmPolylineIcon
21+
*/
22+
@Directive({selector: 'agm-polyline agm-icon-sequence'})
23+
export class AgmPolylineIcon implements OnInit{
24+
25+
/**
26+
* If `true`, each icon in the sequence has the same fixed rotation regardless of the
27+
* angle of the edge on which it lies. Defaults to `false`, in which case each icon
28+
* in the sequence is rotated to align with its edge.
29+
*
30+
* @type {boolean}
31+
* @memberof AgmPolylineIcon
32+
*/
33+
@Input() fixedRotation: boolean;
34+
35+
/**
36+
* The distance from the start of the line at which an icon is to be rendered. This
37+
* distance may be expressed as a percentage of line's length (e.g. '50%') or in pixels
38+
* (e.g. '50px'). Defaults to '100%'.
39+
*
40+
* @type {string}
41+
* @memberof AgmPolylineIcon
42+
*/
43+
@Input() offset: string;
44+
45+
/**
46+
* The distance between consecutive icons on the line. This distance may be expressed as
47+
* a percentage of the line's length (e.g. '50%') or in pixels (e.g. '50px'). To disable
48+
* repeating of the icon, specify '0'. Defaults to '0'.
49+
*
50+
* @type {string}
51+
* @memberof AgmPolylineIcon
52+
*/
53+
@Input() repeat: string;
54+
55+
/**
56+
* The x coordinate of the position of the symbol relative to the polyline. The coordinate
57+
* of the symbol's path is translated _left_ by the anchor's x coordinate. By default, a
58+
* symbol is anchored at (0, 0). The position is expressed in the same coordinate system as the
59+
* symbol's path.
60+
*
61+
* @type {number}
62+
* @memberof AgmPolylineIcon
63+
*/
64+
@Input() anchorX: number;
65+
66+
/**
67+
* The y coordinate of the position of the symbol relative to the polyline. The coordinate
68+
* of the symbol's path is translated _up_ by the anchor's y coordinate. By default, a
69+
* symbol is anchored at (0, 0). The position is expressed in the same coordinate system as the
70+
* symbol's path.
71+
*
72+
* @type {number}
73+
* @memberof AgmPolylineIcon
74+
*/
75+
@Input() anchorY: number;
76+
77+
/**
78+
* The symbol's fill color. All CSS3 colors are supported except for extended named
79+
* colors. Defaults to the stroke color of the corresponding polyline.
80+
*
81+
* @type {string}
82+
* @memberof AgmPolylineIcon
83+
*/
84+
@Input() fillColor: string;
85+
86+
/**
87+
* The symbol's fill opacity. Defaults to 0.
88+
*/
89+
@Input() fillOpacity: number;
90+
91+
/**
92+
* The symbol's path, which is a built-in symbol path, or a custom path expressed using
93+
* SVG path notation. Required.
94+
*
95+
* @type {SymbolPath}
96+
* @memberof AgmPolylineIcon
97+
*/
98+
@Input() path: 'CIRCLE'|'BACKWARD_CLOSED_ARROW'|'BACKWARD_OPEN_ARROW'|'FORWARD_CLOSED_ARROW'|
99+
'FORWARD_OPEN_ARROW' | string;
100+
101+
/**
102+
* The angle by which to rotate the symbol, expressed clockwise in degrees.
103+
* Defaults to 0. A symbol where `fixedRotation` is `false` is rotated relative to
104+
* the angle of the edge on which it lies.
105+
*
106+
* @type {number}
107+
* @memberof AgmPolylineIcon
108+
*/
109+
@Input() rotation: number;
110+
111+
/**
112+
* The amount by which the symbol is scaled in size. Defaults to the stroke weight
113+
* of the polyline; after scaling, the symbol must lie inside a square 22 pixels in
114+
* size centered at the symbol's anchor.
115+
*
116+
* @type {number}
117+
* @memberof AgmPolylineIcon
118+
*/
119+
@Input() scale: number;
120+
121+
/**
122+
* The symbol's stroke color. All CSS3 colors are supported except for extended named
123+
* colors. Defaults to the stroke color of the polyline.
124+
*
125+
* @type {string}
126+
* @memberof AgmPolylineIcon
127+
*/
128+
@Input() strokeColor: string;
129+
130+
/**
131+
* The symbol's stroke opacity. Defaults to the stroke opacity of the polyline.
132+
*
133+
* @type {number}
134+
* @memberof AgmPolylineIcon
135+
*/
136+
@Input() strokeOpacity: number;
137+
138+
/**
139+
* The symbol's stroke weight. Defaults to the scale of the symbol.
140+
*
141+
* @type {number}
142+
* @memberof AgmPolylineIcon
143+
*/
144+
@Input() strokeWeight: number;
145+
146+
ngOnInit(): void {
147+
if (this.path == null) {
148+
throw new Error('Icon Sequence path is required');
149+
}
150+
}
151+
}

packages/core/directives/polyline-point.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {LatLngLiteral} from '../../core/services/google-maps-types';
33

44
/**
55
* AgmPolylinePoint represents one element of a polyline within a {@link
6-
* SembGoogleMapPolyline}
6+
* AgmPolyline}
77
*/
88
@Directive({selector: 'agm-polyline-point'})
99
export class AgmPolylinePoint implements OnChanges {

packages/core/directives/polyline.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Subscription } from 'rxjs';
44
import { PolyMouseEvent, LatLng } from '../services/google-maps-types';
55
import { PolylineManager } from '../services/managers/polyline-manager';
66
import { AgmPolylinePoint } from './polyline-point';
7+
import { AgmPolylineIcon } from './polyline-icon';
78

89
let polylineId = 0;
910
/**
@@ -153,6 +154,8 @@ export class AgmPolyline implements OnDestroy, OnChanges, AfterContentInit {
153154
*/
154155
@ContentChildren(AgmPolylinePoint) points: QueryList<AgmPolylinePoint>;
155156

157+
@ContentChildren(AgmPolylineIcon) iconSequences: QueryList<AgmPolylineIcon>;
158+
156159
private static _polylineOptionsAttributes: Array<string> = [
157160
'draggable', 'editable', 'visible', 'geodesic', 'strokeColor', 'strokeOpacity', 'strokeWeight',
158161
'zIndex'
@@ -176,9 +179,12 @@ export class AgmPolyline implements OnDestroy, OnChanges, AfterContentInit {
176179
if (!this._polylineAddedToManager) {
177180
this._init();
178181
}
179-
const s = this.points.changes.subscribe(() => this._polylineManager.updatePolylinePoints(this));
180-
this._subscriptions.push(s);
182+
const pointSub = this.points.changes.subscribe(() => this._polylineManager.updatePolylinePoints(this));
183+
this._subscriptions.push(pointSub);
181184
this._polylineManager.updatePolylinePoints(this);
185+
186+
const iconSub = this.iconSequences.changes.subscribe(() => this._polylineManager.updateIconSequences(this));
187+
this._subscriptions.push(iconSub);
182188
}
183189

184190
ngOnChanges(changes: SimpleChanges): any {
@@ -237,6 +243,13 @@ export class AgmPolyline implements OnDestroy, OnChanges, AfterContentInit {
237243
return [];
238244
}
239245

246+
_getIcons(): Array<AgmPolylineIcon> {
247+
if (this.iconSequences) {
248+
return this.iconSequences.toArray();
249+
}
250+
return [];
251+
}
252+
240253
/** @internal */
241254
id(): string { return this._id; }
242255

packages/core/map-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export {
88
LatLngBoundsLiteral,
99
LatLngLiteral,
1010
PolyMouseEvent,
11-
MarkerLabel
11+
MarkerLabel,
1212
} from './services/google-maps-types';
1313

1414
/**

packages/core/services/google-maps-types.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@ export interface Point {
278278
export interface GoogleSymbol {
279279
anchor?: Point;
280280
fillColor?: string;
281-
fillOpacity?: string;
281+
fillOpacity?: number;
282282
labelOrigin?: Point;
283-
path?: string;
283+
path?: string | SymbolPath;
284284
rotation?: number;
285285
scale?: number;
286286
strokeColor?: string;
@@ -295,6 +295,14 @@ export interface IconSequence {
295295
repeat?: string;
296296
}
297297

298+
export enum SymbolPath {
299+
BACKWARD_CLOSED_ARROW = 3,
300+
BACKWARD_OPEN_ARROW = 4,
301+
CIRCLE = 0,
302+
FORWARD_CLOSED_ARROW = 1,
303+
FORWARD_OPEN_ARROW = 2,
304+
}
305+
298306
export interface PolylineOptions {
299307
clickable?: boolean;
300308
draggable?: boolean;

0 commit comments

Comments
 (0)