diff --git a/src/front/map.js b/src/front/map.js index 0216792..35793c0 100644 --- a/src/front/map.js +++ b/src/front/map.js @@ -16,7 +16,7 @@ const LineString = require('ol/geom/LineString').default; const proj = require('ol/proj'); -const {Style, Fill, Stroke, Circle} = require('ol/style'); +const {Style, Fill, Stroke, Circle, Icon} = require('ol/style'); const color = require('color'); const mapboxToken = `pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\ @@ -76,6 +76,13 @@ const makeBorderColor = mainColor => return hsl.hex(); }; +const makeCourseColor = mainColor => +{ + const hsl = color(mainColor).hsl(); + hsl.color = Math.max(0, hsl.color[2] += 10); + return hsl.hex(); +}; + const segmentBorderStyle = feature => new Style({ stroke: new Stroke({ color: makeBorderColor(feature.get('colors')[0]), @@ -103,18 +110,56 @@ const stopStyle = 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 courseStyles = {}; + +const getCourseStyle = color => +{ + if (!(color in courseStyles)) + { + const icon = document.createElement('canvas'); + + const iconSize = 35; + const shapeSize = 15; + + icon.width = iconSize; + icon.height = iconSize * 0.6; + + const cx = icon.width / 2; + const cy = icon.height / 2; + + const iconCtx = icon.getContext('2d'); + + for (let [color, size] of [ + [makeBorderColor(color), 13], + [color, 10], + [makeCourseColor(color), 7] + ]) + { + iconCtx.fillStyle = color; + iconCtx.strokeStyle = color; + iconCtx.lineWidth = size; + iconCtx.lineJoin = 'round'; + iconCtx.miterLimit = 200000; + + iconCtx.beginPath(); + iconCtx.moveTo(cx - 0.5 * shapeSize, cy - 0.3 * shapeSize); + iconCtx.lineTo(cx + 0.5 * shapeSize, cy); + iconCtx.lineTo(cx - 0.5 * shapeSize, cy + 0.3 * shapeSize); + iconCtx.closePath(); + iconCtx.stroke(); + iconCtx.fill(); + } + + courseStyles[color] = new Style({ + image: new Icon({ + img: icon, + imgSize: [icon.width, icon.height], + }), + }); + } + + return courseStyles[color]; +}; const createMap = target => { @@ -162,7 +207,7 @@ const createMap = target => // Setup map const view = new View({ center: proj.fromLonLat([3.88, 43.605]), - zoom: 13, + zoom: 14, maxZoom: 22, constrainResolution: true, }); @@ -199,10 +244,17 @@ const createMap = target => = stopsLayer.renderer_.inversePixelTransform; const ctx = getVectorContext(ev); - ctx.setStyle(courseStyle); + let rotation = 0; for (let course of Object.values(simulInstance.courses)) { + const color = network.lines[course.line].color; + const style = getCourseStyle(color); + + style.getImage().setRotation(rotation * Math.PI / 16); + rotation += 1; + ctx.setStyle(style); + const point = new Point(course.position); ctx.drawGeometry(point); }