Immediate rendering of courses
This commit is contained in:
parent
f080bb808e
commit
1f8a78e399
132
src/front/map.js
132
src/front/map.js
|
@ -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
|
|
||||||
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
|
// Setup map
|
||||||
|
const view = new View({
|
||||||
|
center: proj.fromLonLat([3.88, 43.605]),
|
||||||
|
zoom: 13,
|
||||||
|
maxZoom: 22,
|
||||||
|
constrainResolution: true,
|
||||||
|
});
|
||||||
|
|
||||||
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 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;
|
return map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue