tracktracker/src/front/map/index.js

104 lines
3.0 KiB
JavaScript

import "maplibre-gl/dist/maplibre-gl.css";
import * as maplibre from "maplibre-gl";
import * as network from "./network";
import * as vehicles from "./vehicles";
import style from "./assets/style.json";
export default class Map extends EventTarget {
/**
* Instantiate a map.
* @param {string|HTMLElement} target HTML container to add the map to.
* @param {Array<string>} bounds Initial map bounds.
* @param {string} apiKey MapTiler API key.
*/
constructor(target, bounds, apiKey) {
super();
// Replace map key placeholder in style definition
const thisStyle = JSON.parse(JSON.stringify(style));
thisStyle.sources.openmaptiles.url = (
style.sources.openmaptiles.url.replace("{key}", apiKey)
);
thisStyle.glyphs = style.glyphs.replace("{key}", apiKey);
// Initialize MapLibre renderer
this._renderer = new maplibre.Map({
container: target,
bounds,
style: thisStyle,
maplibreLogo: true,
maxPitch: 70,
});
this._renderer.on("load", () => {
network.addLayers(this._renderer);
vehicles.addLayers(this._renderer, courses => {
this.dispatchEvent(new CustomEvent(
"click-courses",
{detail: courses}
));
});
// Move 3D buildings to the front of custom layers
this._renderer.moveLayer("building-3d");
this.dispatchEvent(new CustomEvent("ready"));
});
this._renderer.addControl(new maplibre.NavigationControl());
// Last known courses state
this._courses = null;
// ID of a course to follow
this._follow = null;
}
/** Stop following a course. */
unfollow() {
this._follow = null;
}
/**
* Start following a course with the camera.
* @param {string} courseId The ID of the course to follow.
*/
follow(courseId) {
if (courseId in this._courses) {
this._follow = courseId;
const course = this._courses[courseId];
this._renderer.flyTo({
center: course.geometry.coordinates,
bearing: course.properties.bearing,
pitch: 60,
zoom: 20,
});
} else {
this._follow = null;
}
}
/** Update the map with new courses state. */
update(courses) {
this._courses = courses;
vehicles.update(this._renderer, courses);
if (this._follow !== null) {
if (this._follow in courses) {
const course = courses[this._follow];
if (course.properties.speed > 0) {
this._renderer.jumpTo({
center: course.geometry.coordinates,
bearing: course.properties.bearing,
});
}
} else {
this._follow = null;
}
}
}
}