Immediate rendering of courses

This commit is contained in:
Mattéo Delabre 2020-07-23 20:49:01 +02:00
parent f080bb808e
commit 1f8a78e399
Signed by: matteo
GPG Key ID: AE3FBD02DC583ABB
1 changed files with 61 additions and 69 deletions

View File

@ -8,6 +8,7 @@ const XYZSource = require('ol/source/XYZ').default;
const VectorLayer = require('ol/layer/Vector').default; const VectorLayer = require('ol/layer/Vector').default;
const VectorSource = require('ol/source/Vector').default; const VectorSource = require('ol/source/Vector').default;
const {getVectorContext} = require('ol/render');
const Feature = require('ol/Feature').default; const Feature = require('ol/Feature').default;
const Point = require('ol/geom/Point').default; const Point = require('ol/geom/Point').default;
@ -75,21 +76,21 @@ const makeBorderColor = mainColor =>
return hsl.hex(); return hsl.hex();
}; };
const segmentsBorderStyle = feature => new Style({ const segmentBorderStyle = feature => new Style({
stroke: new Stroke({ stroke: new Stroke({
color: makeBorderColor(feature.get('colors')[0]), color: makeBorderColor(feature.get('colors')[0]),
width: 8, width: 8,
}), }),
}); });
const segmentsInnerStyle = feature => new Style({ const segmentInnerStyle = feature => new Style({
stroke: new Stroke({ stroke: new Stroke({
color: feature.get('colors')[0], color: feature.get('colors')[0],
width: 6, width: 6,
}), }),
}); });
const stopsStyle = feature => new Style({ const stopStyle = feature => new Style({
image: new Circle({ image: new Circle({
fill: new Fill({ fill: new Fill({
color: feature.get('colors')[0], 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 => const createMap = target =>
{ {
// Map background // Map background
@ -122,7 +136,7 @@ const createMap = target =>
const segmentsBorderLayer = new VectorLayer({ const segmentsBorderLayer = new VectorLayer({
source: segmentsSource, source: segmentsSource,
style: segmentsBorderStyle, style: segmentBorderStyle,
updateWhileInteracting: true, updateWhileInteracting: true,
updateWhileAnimating: true, updateWhileAnimating: true,
@ -130,7 +144,7 @@ const createMap = target =>
const segmentsInnerLayer = new VectorLayer({ const segmentsInnerLayer = new VectorLayer({
source: segmentsSource, source: segmentsSource,
style: segmentsInnerStyle, style: segmentInnerStyle,
updateWhileInteracting: true, updateWhileInteracting: true,
updateWhileAnimating: true, updateWhileAnimating: true,
@ -138,71 +152,21 @@ const createMap = target =>
const stopsLayer = new VectorLayer({ const stopsLayer = new VectorLayer({
source: stopsSource, source: stopsSource,
style: stopsStyle, style: stopStyle,
minZoom: 13, minZoom: 13,
updateWhileInteracting: true, updateWhileInteracting: true,
updateWhileAnimating: true, updateWhileAnimating: true,
}); });
// Dynamic data overlay // Setup map
const coursesSource = new VectorSource(); const view = new View({
center: proj.fromLonLat([3.88, 43.605]),
const onFrame = courses => zoom: 13,
{ maxZoom: 22,
// Remove stale courses constrainResolution: true,
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 map = new Map({ const map = new Map({
target, target,
layers: [ layers: [
@ -210,16 +174,44 @@ const createMap = target =>
segmentsBorderLayer, segmentsBorderLayer,
segmentsInnerLayer, segmentsInnerLayer,
stopsLayer, stopsLayer,
coursesLayer,
], ],
view: new View({ view,
center: proj.fromLonLat([3.88, 43.605]),
zoom: 13,
maxZoom: 22,
constrainResolution: true,
}),
}); });
// 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 layers 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 layers 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; return map;
}; };