Skip to content

Commit

Permalink
Location: Added an animated marker, closes #1129.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobwod committed Jun 28, 2022
1 parent 2c2c932 commit 0eb04a3
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions new-client/src/plugins/Location/LocationModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import Feature from "ol/Feature.js";
import Point from "ol/geom/Point.js";
import { Vector as VectorLayer } from "ol/layer.js";
import { Vector as VectorSource } from "ol/source.js";
import { easeOut } from "ol/easing";
import { getVectorContext } from "ol/render";
import { unByKey } from "ol/Observable";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style.js";

class LocationModel {
Expand Down Expand Up @@ -119,9 +122,63 @@ class LocationModel {
else {
this.layer.getSource().addFeature(this.accuracyFeature);
this.layer.getSource().addFeature(this.positionFeature);

// Finally, start flashing the position feature
setInterval(() => {
this.flash(this.positionFeature);
}, 3000);
}
};

// Flash handler: sets up the animation and creats a handler for the postrender
flash = (feature) => {
// Helper: takes care of the actual animation.
const animate = (event) => {
console.log("event: ", event);
// Event is the postrender event that happens - surprise - after render,
// because we actually tell the map to render (see at the end of this function)
const frameState = event.frameState;
const elapsed = frameState.time - start;
if (elapsed >= duration) {
// Remove the listener when time has elapsed
unByKey(listenerKey);
return;
}

// Grab the context that will hold our animated feature
const vectorContext = getVectorContext(event);
const elapsedRatio = elapsed / duration;

// Radius will be 5 at start and 30 at end
const radius = easeOut(elapsedRatio) * 25 + 5;
const opacity = easeOut(1 - elapsedRatio);

const style = new Style({
image: new CircleStyle({
radius: radius,
stroke: new Stroke({
color: "rgba(255, 0, 0, " + opacity + ")",
width: 0.25 + opacity,
}),
}),
});

vectorContext.setStyle(style);
vectorContext.drawGeometry(flashGeom);

// This ensure that the listener for postrender will be triggered
this.map.render();
};

// Setup the animation
const duration = 3000;
const start = Date.now();
// Prepare the feature that will get animated
const flashGeom = feature.getGeometry().clone();
// Save the listener key so we can unsubscribe when animation is done
const listenerKey = this.layer.on("postrender", animate);
};

enable() {
this.toggleTracking(true);
}
Expand Down

0 comments on commit 0eb04a3

Please sign in to comment.