Skip to content

Commit

Permalink
Add stop animation button and playback rate option
Browse files Browse the repository at this point in the history
  • Loading branch information
gtkirk committed Feb 28, 2024
1 parent 0eb3ee6 commit eac852d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 31 deletions.
70 changes: 40 additions & 30 deletions src/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const DEFAULT_OPTIONS = {
weight: 3,
radius: 5,
opacity: 0.5
},
animationOptions: {
playbackRate: 300
}
};

Expand All @@ -47,6 +50,8 @@ export default class GpxMap {
preferCanvas: true,
});

this.trackAnimationFrame = undefined;

let fillStroke = leaflet.Canvas.prototype._fillStroke;
leaflet.Canvas.prototype._fillStroke = (ctx, layer) => {
let compositeOperation = ctx.globalCompositeOperation;
Expand All @@ -56,7 +61,6 @@ export default class GpxMap {
}

leaflet.easyButton({
type: 'animate',
states: [{
icon: 'fa-camera fa-lg',
stateName: 'default',
Expand All @@ -79,7 +83,6 @@ export default class GpxMap {
}).addTo(this.map);

leaflet.easyButton({
type: 'animate',
states: [{
icon: 'fa-sliders fa-lg',
stateName: 'default',
Expand All @@ -94,7 +97,6 @@ export default class GpxMap {
}).addTo(this.map);

leaflet.easyButton({
type: 'animate',
states: [{
icon: 'fa-filter fa-lg',
stateName: 'default',
Expand All @@ -109,7 +111,6 @@ export default class GpxMap {
}).addTo(this.map);

this.viewAll = leaflet.easyButton({
type: 'animate',
states: [{
icon: 'fa-map fa-lg',
stateName: 'default',
Expand All @@ -121,13 +122,21 @@ export default class GpxMap {
}).addTo(this.map);

this.animate = leaflet.easyButton({
type: 'animate',
states: [{
icon: 'fa-play fa-lg',
steateName: 'default',
stateName: 'default',
title: 'Play',
onClick: () => {
this.animateTracks();
onClick: (btn) => {
btn.state('running');
this.animateTracks(btn);
},
},{
icon: 'fa-stop fa-lg',
stateName: 'running',
title: 'Stop',
onClick: (btn) => {
btn.state('default');
this.stopAnimation(btn);
},
}],
}).addTo(this.map);
Expand Down Expand Up @@ -348,9 +357,8 @@ export default class GpxMap {
}
}

animateTracks()
animateTracks(btn)
{
this.animate.disable();
let visibleTracks = this.tracks.filter(t => t.visible);
if (visibleTracks.length === 0 && this.imageMarkers.length === 0) {
return;
Expand All @@ -360,7 +368,6 @@ export default class GpxMap {
let maxBound = Math.max(...visibleTracks.map(t => t.points[t.points.length - 1].timestamp - t.points[0].timestamp));

let start, previousTimeStamp;
const markers = [];

const animate = step.bind(this);

Expand All @@ -371,58 +378,61 @@ export default class GpxMap {
start = timestamp;
}
const elapsed = timestamp - start;
const stepTime = minBound + (elapsed * 300);
const stepTime = minBound + (elapsed * this.options.animationOptions.playbackRate);


if (previousTimeStamp !== timestamp)
{
for (let i = 0; i < visibleTracks.length; i++)
for (const track of visibleTracks)
{

const track = visibleTracks[i];
const trackStepTime = stepTime + +track.points[0].timestamp;
const point = track.points.find(pt => pt.timestamp > trackStepTime);

if (point)
{
if (markers[i])
if (track.marker)
{
markers[i].setLatLng([point.lat, point.lng]);
track.marker.setLatLng([point.lat, point.lng]);
track.line.addLatLng([point.lat, point.lng]);
}
else
{
markers[i] = leaflet.circleMarker([point.lat, point.lng], { color: '#3388ff', fill: true, fillOpacity: 0.5, pane: 'markerPane' });
markers[i].addTo(this.map);
track.marker = leaflet.circleMarker([point.lat, point.lng], { color: '#3388ff', fill: true, fillOpacity: 0.5, pane: 'markerPane' });
track.marker.addTo(this.map);
track.line.setLatLngs([]);
}
}
else
{
if (markers[i])
{
markers[i].remove();
}
track.marker?.remove();
delete track.marker;
}
}
}

if (stepTime < maxBound)
{
previousTimeStamp = timestamp;
window.requestAnimationFrame(animate);
this.trackAnimationRequest = window.requestAnimationFrame(animate);
}
else
{
for (let marker of markers)
{
marker.remove();
}
this.animate.enable();
btn.state('default');
}
}

window.requestAnimationFrame(animate);
this.trackAnimationRequest = window.requestAnimationFrame(animate);
}

stopAnimation(btn)
{
window.cancelAnimationFrame(this.trackAnimationRequest);
this.tracks.forEach(track => {
track.marker?.remove();
delete track.marker;
track.line.setLatLngs(track.points);
})

}

screenshot(format, domNode) {
Expand Down
16 changes: 15 additions & 1 deletion src/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,16 @@ export function buildSettingsModal(tracks, opts, updateCallback) {
</fieldset>
<fieldset class="form-group">
<legend>Animation</legend>
<div class="row">
<label>Playback Rate</label>
<input name="playbackRate" type="number" value=${opts.animationOptions.playbackRate}>
</div>
</fieldset>
<span class="form-row">
<label>Override existing tracks</label>
<input name="overrideExisting" type="checkbox" ${overrideExisting}>
Expand Down Expand Up @@ -417,6 +427,10 @@ export function buildSettingsModal(tracks, opts, updateCallback) {
options.lineOptions[opt] = elements[opt].checked;
}

for (let opt of ['playbackRate']) {
options.animationOptions[opt] = elements[opt].value;
}

updateCallback(options);
};

Expand All @@ -429,7 +443,7 @@ export function buildSettingsModal(tracks, opts, updateCallback) {
let elements = document.getElementById('settings').elements;
for (let opt of ['theme', 'color', 'weight', 'opacity', 'markerColor',
'markerWeight', 'markerOpacity', 'markerRadius',
'newDate', 'detectColors', 'singleColor', 'highlightNew']) {
'newDate', 'detectColors', 'singleColor', 'highlightNew', 'playbackRate']) {
elements[opt].addEventListener('change', applyOptions);
}
});
Expand Down

0 comments on commit eac852d

Please sign in to comment.