Immediate rendering of courses
This commit is contained in:
parent
f080bb808e
commit
1f8a78e399
130
src/front/map.js
130
src/front/map.js
|
@ -8,6 +8,7 @@ const XYZSource = require('ol/source/XYZ').default;
|
|||
|
||||
const VectorLayer = require('ol/layer/Vector').default;
|
||||
const VectorSource = require('ol/source/Vector').default;
|
||||
const {getVectorContext} = require('ol/render');
|
||||
|
||||
const Feature = require('ol/Feature').default;
|
||||
const Point = require('ol/geom/Point').default;
|
||||
|
@ -75,21 +76,21 @@ const makeBorderColor = mainColor =>
|
|||
return hsl.hex();
|
||||
};
|
||||
|
||||
const segmentsBorderStyle = feature => new Style({
|
||||
const segmentBorderStyle = feature => new Style({
|
||||
stroke: new Stroke({
|
||||
color: makeBorderColor(feature.get('colors')[0]),
|
||||
width: 8,
|
||||
}),
|
||||
});
|
||||
|
||||
const segmentsInnerStyle = feature => new Style({
|
||||
const segmentInnerStyle = feature => new Style({
|
||||
stroke: new Stroke({
|
||||
color: feature.get('colors')[0],
|
||||
width: 6,
|
||||
}),
|
||||
});
|
||||
|
||||
const stopsStyle = feature => new Style({
|
||||
const stopStyle = feature => new Style({
|
||||
image: new Circle({
|
||||
fill: new Fill({
|
||||
color: feature.get('colors')[0],
|
||||
|
@ -102,6 +103,19 @@ const stopsStyle = feature => new Style({
|
|||
}),
|
||||
});
|
||||
|
||||
const courseStyle = new Style({
|
||||
image: new Circle({
|
||||
fill: new Fill({
|
||||
color: '#FF0000',
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: makeBorderColor('#FF0000'),
|
||||
width: 1.5,
|
||||
}),
|
||||
radius: 6,
|
||||
}),
|
||||
});
|
||||
|
||||
const createMap = target =>
|
||||
{
|
||||
// Map background
|
||||
|
@ -122,7 +136,7 @@ const createMap = target =>
|
|||
|
||||
const segmentsBorderLayer = new VectorLayer({
|
||||
source: segmentsSource,
|
||||
style: segmentsBorderStyle,
|
||||
style: segmentBorderStyle,
|
||||
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true,
|
||||
|
@ -130,7 +144,7 @@ const createMap = target =>
|
|||
|
||||
const segmentsInnerLayer = new VectorLayer({
|
||||
source: segmentsSource,
|
||||
style: segmentsInnerStyle,
|
||||
style: segmentInnerStyle,
|
||||
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true,
|
||||
|
@ -138,71 +152,21 @@ const createMap = target =>
|
|||
|
||||
const stopsLayer = new VectorLayer({
|
||||
source: stopsSource,
|
||||
style: stopsStyle,
|
||||
style: stopStyle,
|
||||
|
||||
minZoom: 13,
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true,
|
||||
});
|
||||
|
||||
// Dynamic data overlay
|
||||
const coursesSource = new VectorSource();
|
||||
|
||||
const onFrame = courses =>
|
||||
{
|
||||
// Remove stale courses
|
||||
for (let feature of coursesSource.getFeatures())
|
||||
{
|
||||
if (!(feature.getId() in courses))
|
||||
{
|
||||
coursesSource.removeFeature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new courses or update existing courses
|
||||
const newFeatures = [];
|
||||
|
||||
for (let [courseId, course] of Object.entries(courses))
|
||||
{
|
||||
if ('position' in course)
|
||||
{
|
||||
const feature = coursesSource.getFeatureById(courseId);
|
||||
const coords = proj.fromLonLat([
|
||||
course.position.lon,
|
||||
course.position.lat
|
||||
]);
|
||||
|
||||
if (feature === null)
|
||||
{
|
||||
const feature = new Feature({
|
||||
colors: ['#FF0000'],
|
||||
geometry: new Point(coords)
|
||||
});
|
||||
|
||||
feature.setId(courseId);
|
||||
newFeatures.push(feature);
|
||||
}
|
||||
else
|
||||
{
|
||||
feature.getGeometry().setCoordinates(coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
coursesSource.addFeatures(newFeatures);
|
||||
};
|
||||
|
||||
simulation.run(onFrame);
|
||||
|
||||
const coursesLayer = new VectorLayer({
|
||||
source: coursesSource,
|
||||
style: stopsStyle,
|
||||
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true,
|
||||
// Setup map
|
||||
const view = new View({
|
||||
center: proj.fromLonLat([3.88, 43.605]),
|
||||
zoom: 13,
|
||||
maxZoom: 22,
|
||||
constrainResolution: true,
|
||||
});
|
||||
|
||||
// Setup map
|
||||
const map = new Map({
|
||||
target,
|
||||
layers: [
|
||||
|
@ -210,16 +174,44 @@ const createMap = target =>
|
|||
segmentsBorderLayer,
|
||||
segmentsInnerLayer,
|
||||
stopsLayer,
|
||||
coursesLayer,
|
||||
],
|
||||
view: new View({
|
||||
center: proj.fromLonLat([3.88, 43.605]),
|
||||
zoom: 13,
|
||||
maxZoom: 22,
|
||||
constrainResolution: true,
|
||||
}),
|
||||
view,
|
||||
});
|
||||
|
||||
// Run courses simulation and draw directly on the map
|
||||
const simulInstance = simulation.start();
|
||||
|
||||
map.on('postcompose', ev =>
|
||||
{
|
||||
simulInstance.update();
|
||||
|
||||
// The normal way to access a layer’s vector context is through the
|
||||
// `postrender` event of that layer. However, `postrender` is not
|
||||
// triggered when no feature of the layer is inside the current
|
||||
// bounding box, but we want to draw vehicles in between stops even
|
||||
// if no stop is visible. This hack listens to the global `postcompose`
|
||||
// event, which is always triggered at every frame, and reconstructs
|
||||
// the stops layer’s vector context from internal variables
|
||||
if (stopsLayer.renderer_)
|
||||
{
|
||||
ev.context = stopsLayer.renderer_.context;
|
||||
ev.inversePixelTransform
|
||||
= stopsLayer.renderer_.inversePixelTransform;
|
||||
|
||||
const ctx = getVectorContext(ev);
|
||||
ctx.setStyle(courseStyle);
|
||||
|
||||
for (let course of Object.values(simulInstance.courses))
|
||||
{
|
||||
const point = new Point(course.position);
|
||||
ctx.drawGeometry(point);
|
||||
}
|
||||
}
|
||||
|
||||
map.render();
|
||||
});
|
||||
|
||||
map.render();
|
||||
return map;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue