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