Show course informations in side pane
This commit is contained in:
parent
fe08c42920
commit
d9869ce2f7
|
@ -7,21 +7,31 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
|
||||
<style>
|
||||
body, html
|
||||
{
|
||||
body, html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#map
|
||||
{
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#informations {
|
||||
flex: 0 0 600px;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="informations"></div>
|
||||
<div id="map"></div>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
|
|
|
@ -1,6 +1,89 @@
|
|||
// eslint-disable-next-line node/no-extraneous-require
|
||||
require("regenerator-runtime/runtime");
|
||||
|
||||
const network = require("../tam/network.json");
|
||||
const simulation = require("../tam/simulation");
|
||||
const map = require("./map/index.js");
|
||||
|
||||
map.create(/* map = */ "map");
|
||||
// Run courses simulation
|
||||
const coursesSimulation = simulation.start();
|
||||
global.courses = coursesSimulation.courses;
|
||||
|
||||
const informations = document.querySelector("#informations");
|
||||
let courseId = null;
|
||||
|
||||
const displayTime = date => [
|
||||
date.getHours(),
|
||||
date.getMinutes(),
|
||||
date.getSeconds()
|
||||
].map(number => number.toString().padStart(2, '0')).join(':');
|
||||
|
||||
setInterval(() => {
|
||||
let html = `
|
||||
<dl>
|
||||
<dt>Heure actuelle</dt>
|
||||
<dd>${displayTime(new Date())}</dd>
|
||||
</dl>
|
||||
`;
|
||||
|
||||
if (courseId !== null && courseId in coursesSimulation.courses) {
|
||||
const course = coursesSimulation.courses[courseId];
|
||||
|
||||
const timeToHTML = time => Math.ceil((time - Date.now()) / 1000);
|
||||
|
||||
const stopToHTML = stopId => network.stops[stopId].properties.name;
|
||||
|
||||
const passingsToHTML = passings => passings.map(([stopId, time]) => `
|
||||
<tr>
|
||||
<td>${stopToHTML(stopId)}</td>
|
||||
<td>${displayTime(new Date(time))}</td>
|
||||
</tr>
|
||||
`).join('\n');
|
||||
|
||||
html += `
|
||||
<dl>
|
||||
<dt>ID</dt>
|
||||
<dd>${courseId}</dd>
|
||||
|
||||
<dt>Ligne</dt>
|
||||
<dd>${course.line}</dd>
|
||||
|
||||
<dt>Destination</dt>
|
||||
<dd>${stopToHTML(course.finalStop)}</dd>
|
||||
|
||||
<dt>État</dt>
|
||||
<dd>${course.state === 'moving'
|
||||
? `Entre ${stopToHTML(course.departureStop)}
|
||||
et ${stopToHTML(course.arrivalStop)}`
|
||||
: `À l’arrêt ${stopToHTML(course.currentStop)}`}</dd>
|
||||
|
||||
${course.state === 'moving' ? `
|
||||
<dt>Arrivée dans</dt>
|
||||
<dd>${timeToHTML(course.arrivalTime)} s</dd>
|
||||
|
||||
<dt>Distance parcourue</dt>
|
||||
<dd>${Math.ceil(course.traveledDistance)} m</dd>
|
||||
|
||||
<dt>Vitesse</dt>
|
||||
<dd>${Math.ceil(course.speed * 3600)} km/h</dd>
|
||||
` : `
|
||||
<dt>Départ dans</dt>
|
||||
<dd>${timeToHTML(course.departureTime)} s</dd>
|
||||
`}
|
||||
</dl>
|
||||
|
||||
<h2>Arrêts précédents</h2>
|
||||
<table>${passingsToHTML(course.prevPassings)}</table>
|
||||
|
||||
<h2>Arrêts suivants</h2>
|
||||
<table>${passingsToHTML(course.nextPassings)}</table>
|
||||
`;
|
||||
}
|
||||
|
||||
informations.innerHTML = html;
|
||||
}, 1000);
|
||||
|
||||
// Create the network and courses map
|
||||
map.create(/* map = */ "map", coursesSimulation, course => {
|
||||
courseId = course;
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@ const tilesLayers = require("./tiles");
|
|||
const networkLayers = require("./network");
|
||||
const { sizes, makeBorderColor, makeCourseColor } = require("./common");
|
||||
const network = require("../../tam/network.json");
|
||||
const simulation = require("../../tam/simulation");
|
||||
|
||||
const courseStyles = {};
|
||||
|
||||
|
@ -59,7 +58,7 @@ const getCourseStyle = lineColor => {
|
|||
return courseStyles[lineColor];
|
||||
};
|
||||
|
||||
const create = target => {
|
||||
const create = (target, coursesSimulation, onClick) => {
|
||||
const view = new View({
|
||||
center: proj.fromLonLat([3.88, 43.605]),
|
||||
zoom: 14,
|
||||
|
@ -78,32 +77,9 @@ const create = target => {
|
|||
|
||||
const stopsLayer = map.getLayers().item(3);
|
||||
|
||||
// Run courses simulation
|
||||
const simulInstance = simulation.start();
|
||||
|
||||
// Course on which the view is currently focused
|
||||
let focusedCourse = null;
|
||||
|
||||
const startFocus = courseId => {
|
||||
if (courseId in simulInstance.courses) {
|
||||
const course = simulInstance.courses[courseId];
|
||||
|
||||
view.animate({
|
||||
center: course.position,
|
||||
duration: 500
|
||||
}, () => {
|
||||
focusedCourse = courseId;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const stopFocus = () => {
|
||||
focusedCourse = null;
|
||||
};
|
||||
|
||||
// Draw courses directly on the map
|
||||
map.on("postcompose", ev => {
|
||||
simulInstance.update();
|
||||
coursesSimulation.update();
|
||||
|
||||
// The normal way to access a layer’s vector context is through the
|
||||
// `postrender` event of that layer. However, `postrender` is not
|
||||
|
@ -121,7 +97,8 @@ const create = target => {
|
|||
|
||||
const ctx = getVectorContext(ev);
|
||||
|
||||
for (const course of Object.values(simulInstance.courses)) {
|
||||
for (const course of Object.values(coursesSimulation.courses)) {
|
||||
const point = new Point(course.position);
|
||||
const color = network.lines[course.line].color;
|
||||
const style = getCourseStyle(color);
|
||||
|
||||
|
@ -131,14 +108,7 @@ const create = target => {
|
|||
);
|
||||
|
||||
ctx.setStyle(style);
|
||||
|
||||
const point = new Point(course.position);
|
||||
|
||||
ctx.drawGeometry(point);
|
||||
|
||||
if (course.id === focusedCourse) {
|
||||
view.setCenter(course.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,22 +119,18 @@ const create = target => {
|
|||
|
||||
map.on("singleclick", ev => {
|
||||
const mousePixel = map.getPixelFromCoordinate(ev.coordinate);
|
||||
const maxDistance = sizes.courseSize + sizes.courseOuterBorder;
|
||||
const maxDistance = sizes.courseSize + sizes.courseInnerBorder;
|
||||
|
||||
for (const course of Object.values(simulInstance.courses)) {
|
||||
for (const course of Object.values(coursesSimulation.courses)) {
|
||||
const coursePixel = map.getPixelFromCoordinate(course.position);
|
||||
const dx = mousePixel[0] - coursePixel[0];
|
||||
const dy = mousePixel[1] - coursePixel[1];
|
||||
const distance = dx * dx + dy * dy;
|
||||
|
||||
if (distance <= maxDistance * maxDistance) {
|
||||
startFocus(course.id);
|
||||
return;
|
||||
onClick(course.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Clicking anywhere else resets focus
|
||||
stopFocus();
|
||||
});
|
||||
|
||||
return map;
|
||||
|
|
Loading…
Reference in New Issue