Animate a Point along a Route
Use Turf to smoothly animate a point along the distance of a line.x
163
1
2
<html lang="en">
3
<head>
4
<meta charset="utf-8" />
5
<link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.css" />
6
<script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.js"></script>
7
<script src="https://unpkg.com/@turf/turf/turf.min.js"></script>
8
<style>
9
body { margin: 0; padding: 0; }
10
#map {
11
position: absolute;
12
top: 0;
13
bottom: 0;
14
width: 100%;
15
}
16
.overlay {
17
position: absolute;
18
top: 10px;
19
left: 10px;
20
}
21
.overlay button {
22
font: 600 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
23
background-color: #3386C0;
24
color: #fff;
25
display: inline-block;
26
margin: 0;
27
padding: 10px 20px;
28
border: none;
29
cursor: pointer;
30
border-radius: 3px;
31
}
32
.overlay button:hover {
33
background-color: #4EA0DA;
34
}
35
</style>
36
</head>
37
<body>
38
<div id="map"></div>
39
<div class= "overlay">
40
<button id="replay">Replay</button>
41
</div>
42
<script>
43
TrimbleMaps.setAPIKey('YOUR_API_KEY_HERE');
44
const map = window.map = new TrimbleMaps.Map({
45
container: 'map', // container id
46
style: TrimbleMaps.Common.Style.TRANSPORTATION, //hosted style id
47
center: [-96, 37.8], // starting position
48
zoom: 3 // starting zoom
49
});
50
// Los Angeles
51
var origin = [-118.2437, 34.0522];
52
// NYC
53
var destination = [-73.99906, 40.72185 ];
54
var route = {
55
type: 'FeatureCollection',
56
features:[
57
{
58
type: 'Feature',
59
geometry: {
60
type: 'LineString',
61
coordinates: [origin, destination]
62
}
63
}
64
]
65
};
66
var point = {
67
type: 'FeatureCollection',
68
features:[
69
{
70
type: 'Feature',
71
properties: {},
72
geometry: {
73
type: 'Point',
74
coordinates: origin
75
}
76
}
77
]
78
};
79
// Getting distance in miles between LA (origin) and NYC (destination)
80
var length = turf.length(route.features[0], {units: 'miles'});
81
var arc = [];
82
var steps = 500;
83
for (var i = 0; i < length; i += length / steps) {
84
var segment = turf.along(route.features[0], i, {units: 'miles'});
85
arc.push(segment.geometry.coordinates);
86
}
87
// Update route with calculated arc coord.
88
route.features[0].geometry.coordinates = arc;
89
// Used to increment the value of the point measurement against the route.
90
var counter = 0;
91
map.on('load', function() {
92
map.addSource('route', {
93
type: 'geojson',
94
data: route
95
});
96
map.addSource('point', {
97
type: 'geojson',
98
data: point
99
});
100
map.addLayer({
101
'id': 'route',
102
'source': 'route',
103
'type': 'line',
104
'paint': {
105
'line-width': 2,
106
'line-color': '#005F9E'
107
}
108
});
109
map.addLayer({
110
'id': 'point',
111
'source': 'point',
112
'type': 'symbol',
113
'layout': {
114
'icon-image': 'poi_airport',
115
'icon-rotate': ['get', 'bearing'],
116
'icon-rotation-alignment': 'map',
117
'icon-allow-overlap': true,
118
'icon-ignore-placement': true
119
}
120
});
121
// Update point coordinates based on counter denoting.
122
function animate() {
123
if (counter >= steps) {
124
return;
125
}
126
127
point.features[0].geometry.coordinates =
128
route.features[0].geometry.coordinates[counter];
129
// Calculate the bearing to ensure the icon is rotated to match the route arc
130
// The bearing is calculate between the current point and the next point, except
131
// at the end of the arc use the previous point and the current point.
132
point.features[0].properties.bearing =
133
turf.bearing(
134
turf.point(
135
route.features[0].geometry.coordinates[
136
counter >= steps - 1 ?
137
counter - 1 : counter
138
]
139
),
140
turf.point(
141
route.features[0].geometry.coordinates[
142
counter >= steps - 1 ? counter : counter + 1
143
]
144
)
145
) -53;
146
map.getSource('point').setData(point);
147
counter = counter + 1;
148
if (counter < steps) {
149
window.requestAnimationFrame(animate);
150
}
151
}
152
document.getElementById('replay').addEventListener('click', function() {
153
point.features[0].geometry.coordinates = origin;
154
map.getSource('point').setData(point);
155
counter = 0;
156
animate(counter);
157
});
158
animate(counter);
159
});
160
</script>
161
</body>
162
</html>
163