Walking Tracker
Animated Walking Tracker with Stats Requires Trimble Maps v4.0.0 or later.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.5.css" />
<script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<style>
body { margin: 0; padding: 0; }
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#stats {
position: absolute;
top: 10px; left: 10px;
background: rgba(0,0,0,0.6);
color: #fff;
padding: 10px 15px;
border-radius: 8px;
font-family: system-ui, sans-serif;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="stats">
<div><b>Walking Tracker</b></div>
<div id="distance">Distance: 0.00 km</div>
<div id="time">Time: 0s</div>
</div>
<script>
TrimbleMaps.setAPIKey('0D8BA43647605743A5FB4B225664EF0F');
const map = new TrimbleMaps.Map({
container: 'map',
center: [-73.968285, 40.785091], // Central Park
zoom: 13,
pitch: 50,
attributionControl: false,
hash: true,
});
// Walking route
const routeCoords = [
[-73.9731, 40.7644],
[-73.9712, 40.7681],
[-73.9690, 40.7725],
[-73.9660, 40.7770],
[-73.9655, 40.7822],
[-73.9685, 40.7851],
[-73.9735, 40.7870],
[-73.9770, 40.7840],
[-73.9790, 40.7785],
[-73.9780, 40.7715],
[-73.9750, 40.7670],
[-73.9731, 40.7644] // loop back
];
const route = turf.lineString(routeCoords);
const routeLength = turf.length(route, {units: 'kilometers'});
let progress = 0;
let distanceTravelled = 0;
const speed = 0.0001; // fraction of route per frame
const startTime = Date.now();
map.on('load', async () => {
// Load custom walking icon
const img = await map.loadImage('https://cdn-icons-png.flaticon.com/512/1077/1077012.png');
map.addImage('walker-icon', img.data, {sdf: false});
// Route line
map.addSource('walk-route', {
type: 'geojson',
data: route
});
map.addLayer({
id: 'walk-route-line',
type: 'line',
source: 'walk-route',
paint: {
'line-color': '#ff7f0e',
'line-width': 4,
'line-dasharray': [2, 2]
}
});
// Walker icon
map.addSource('walker', {
type: 'geojson',
data: turf.point(routeCoords[0])
});
map.addLayer({
id: 'walker',
source: 'walker',
type: 'symbol',
layout: {
'icon-image': 'walker-icon', // ✅ custom loaded image
'icon-size': 0.08, // adjust size
'icon-rotate': ['get', 'bearing'],
'icon-rotation-alignment': 'map'
}
});
function animate() {
progress += speed;
if (progress > 1) progress = 0; // loop again
const dist = progress * routeLength;
const along = turf.along(route, dist, {units: 'kilometers'});
const next = turf.along(route, Math.min(dist + 0.001, routeLength), {units: 'kilometers'});
if (!along || !along.geometry) return;
const bearing = turf.bearing(along, next);
// Update walker position smoothly
map.getSource('walker').setData({
type: 'Feature',
geometry: along.geometry,
properties: {bearing}
});
// Update stats
distanceTravelled = dist;
const elapsedSec = Math.floor((Date.now() - startTime) / 1000);
document.getElementById('distance').innerText =
`Distance: ${distanceTravelled.toFixed(2)} km`;
document.getElementById('time').innerText = `Time: ${elapsedSec}s`;
requestAnimationFrame(animate);
}
animate();
});
</script>
</body>
</html>
Walking Tracker
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.5.css" />
<script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<style>
body { margin: 0; padding: 0; }
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#stats {
position: absolute;
top: 10px; left: 10px;
background: rgba(0,0,0,0.6);
color: #fff;
padding: 10px 15px;
border-radius: 8px;
font-family: system-ui, sans-serif;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="stats">
<div><b>Walking Tracker</b></div>
<div id="distance">Distance: 0.00 km</div>
<div id="time">Time: 0s</div>
</div>
<script>
TrimbleMaps.setAPIKey('0D8BA43647605743A5FB4B225664EF0F');
const map = new TrimbleMaps.Map({
container: 'map',
center: [-73.968285, 40.785091], // Central Park
zoom: 13,
pitch: 50,
attributionControl: false,
hash: true,
});
// Walking route
const routeCoords = [
[-73.9731, 40.7644],
[-73.9712, 40.7681],
[-73.9690, 40.7725],
[-73.9660, 40.7770],
[-73.9655, 40.7822],
[-73.9685, 40.7851],
[-73.9735, 40.7870],
[-73.9770, 40.7840],
[-73.9790, 40.7785],
[-73.9780, 40.7715],
[-73.9750, 40.7670],
[-73.9731, 40.7644] // loop back
];
const route = turf.lineString(routeCoords);
const routeLength = turf.length(route, {units: 'kilometers'});
let progress = 0;
let distanceTravelled = 0;
const speed = 0.0001; // fraction of route per frame
const startTime = Date.now();
map.on('load', async () => {
// Load custom walking icon
const img = await map.loadImage('https://cdn-icons-png.flaticon.com/512/1077/1077012.png');
map.addImage('walker-icon', img.data, {sdf: false});
// Route line
map.addSource('walk-route', {
type: 'geojson',
data: route
});
map.addLayer({
id: 'walk-route-line',
type: 'line',
source: 'walk-route',
paint: {
'line-color': '#ff7f0e',
'line-width': 4,
'line-dasharray': [2, 2]
}
});
// Walker icon
map.addSource('walker', {
type: 'geojson',
data: turf.point(routeCoords[0])
});
map.addLayer({
id: 'walker',
source: 'walker',
type: 'symbol',
layout: {
'icon-image': 'walker-icon', // ✅ custom loaded image
'icon-size': 0.08, // adjust size
'icon-rotate': ['get', 'bearing'],
'icon-rotation-alignment': 'map'
}
});
function animate() {
progress += speed;
if (progress > 1) progress = 0; // loop again
const dist = progress * routeLength;
const along = turf.along(route, dist, {units: 'kilometers'});
const next = turf.along(route, Math.min(dist + 0.001, routeLength), {units: 'kilometers'});
if (!along || !along.geometry) return;
const bearing = turf.bearing(along, next);
// Update walker position smoothly
map.getSource('walker').setData({
type: 'Feature',
geometry: along.geometry,
properties: {bearing}
});
// Update stats
distanceTravelled = dist;
const elapsedSec = Math.floor((Date.now() - startTime) / 1000);
document.getElementById('distance').innerText =
`Distance: ${distanceTravelled.toFixed(2)} km`;
document.getElementById('time').innerText = `Time: ${elapsedSec}s`;
requestAnimationFrame(animate);
}
animate();
});
</script>
</body>
</html>