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" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body, html
|
body, html {
|
||||||
{
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map
|
body {
|
||||||
{
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
#informations {
|
||||||
|
flex: 0 0 600px;
|
||||||
|
padding: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="informations"></div>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,6 +1,89 @@
|
||||||
// eslint-disable-next-line node/no-extraneous-require
|
// eslint-disable-next-line node/no-extraneous-require
|
||||||
require("regenerator-runtime/runtime");
|
require("regenerator-runtime/runtime");
|
||||||
|
|
||||||
|
const network = require("../tam/network.json");
|
||||||
|
const simulation = require("../tam/simulation");
|
||||||
const map = require("./map/index.js");
|
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 networkLayers = require("./network");
|
||||||
const { sizes, makeBorderColor, makeCourseColor } = require("./common");
|
const { sizes, makeBorderColor, makeCourseColor } = require("./common");
|
||||||
const network = require("../../tam/network.json");
|
const network = require("../../tam/network.json");
|
||||||
const simulation = require("../../tam/simulation");
|
|
||||||
|
|
||||||
const courseStyles = {};
|
const courseStyles = {};
|
||||||
|
|
||||||
|
@ -59,7 +58,7 @@ const getCourseStyle = lineColor => {
|
||||||
return courseStyles[lineColor];
|
return courseStyles[lineColor];
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = target => {
|
const create = (target, coursesSimulation, onClick) => {
|
||||||
const view = new View({
|
const view = new View({
|
||||||
center: proj.fromLonLat([3.88, 43.605]),
|
center: proj.fromLonLat([3.88, 43.605]),
|
||||||
zoom: 14,
|
zoom: 14,
|
||||||
|
@ -78,32 +77,9 @@ const create = target => {
|
||||||
|
|
||||||
const stopsLayer = map.getLayers().item(3);
|
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
|
// Draw courses directly on the map
|
||||||
map.on("postcompose", ev => {
|
map.on("postcompose", ev => {
|
||||||
simulInstance.update();
|
coursesSimulation.update();
|
||||||
|
|
||||||
// The normal way to access a layer’s vector context is through the
|
// The normal way to access a layer’s vector context is through the
|
||||||
// `postrender` event of that layer. However, `postrender` is not
|
// `postrender` event of that layer. However, `postrender` is not
|
||||||
|
@ -121,7 +97,8 @@ const create = target => {
|
||||||
|
|
||||||
const ctx = getVectorContext(ev);
|
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 color = network.lines[course.line].color;
|
||||||
const style = getCourseStyle(color);
|
const style = getCourseStyle(color);
|
||||||
|
|
||||||
|
@ -131,14 +108,7 @@ const create = target => {
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.setStyle(style);
|
ctx.setStyle(style);
|
||||||
|
|
||||||
const point = new Point(course.position);
|
|
||||||
|
|
||||||
ctx.drawGeometry(point);
|
ctx.drawGeometry(point);
|
||||||
|
|
||||||
if (course.id === focusedCourse) {
|
|
||||||
view.setCenter(course.position);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,22 +119,18 @@ const create = target => {
|
||||||
|
|
||||||
map.on("singleclick", ev => {
|
map.on("singleclick", ev => {
|
||||||
const mousePixel = map.getPixelFromCoordinate(ev.coordinate);
|
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 coursePixel = map.getPixelFromCoordinate(course.position);
|
||||||
const dx = mousePixel[0] - coursePixel[0];
|
const dx = mousePixel[0] - coursePixel[0];
|
||||||
const dy = mousePixel[1] - coursePixel[1];
|
const dy = mousePixel[1] - coursePixel[1];
|
||||||
const distance = dx * dx + dy * dy;
|
const distance = dx * dx + dy * dy;
|
||||||
|
|
||||||
if (distance <= maxDistance * maxDistance) {
|
if (distance <= maxDistance * maxDistance) {
|
||||||
startFocus(course.id);
|
onClick(course.id);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clicking anywhere else resets focus
|
|
||||||
stopFocus();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
|
|
Loading…
Reference in New Issue