require('ol/ol.css'); const {Map, View} = require('ol'); const TileLayer = require('ol/layer/Tile').default; const XYZSource = require('ol/source/XYZ').default; const VectorLayer = require('ol/layer/Vector').default; const VectorSource = require('ol/source/Vector').default; const Feature = require('ol/Feature').default; const Point = require('ol/geom/Point').default; const LineString = require('ol/geom/LineString').default; const proj = require('ol/proj'); const {Style, Fill, Stroke, Circle} = require('ol/style'); const color = require('color'); // Map background const mapboxToken = 'pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJjazUxaWNsdXcwdWhjM2\ 9tc2xndXJoNGtxIn0.xELwMerqJLFimIqU6RxnZw'; const backgroundSource = new XYZSource({ url: 'https://api.mapbox.com/' + [ 'styles', 'v1', 'mapbox', 'streets-v11', 'tiles', '512', '{z}', '{x}', '{y}', ].join('/') + `?access_token=${mapboxToken}`, tileSize: [512, 512], }); const backgroundLayer = new TileLayer({ source: backgroundSource, }); // Data overlay const dataSource = new VectorSource(); const SERVER = window.origin; fetch(SERVER + '/network').then(res => res.json()).then(network => { const stopPoints = Object.entries(network.stops) .map(([stopId, stop]) => { const feature = new Feature({ type: 'stop', color: network.lines[stop.lines[0]].color, geometry: new Point(proj.fromLonLat([stop.lon, stop.lat])), }); feature.setId(stopId); return feature; }); const segmentLines = Object.entries(network.segments) .map(([segmentId, segment]) => { const feature = new Feature({ type: 'segment', color: network.lines[segment.lines[0]].color, geometry: new LineString(segment.nodes.map( ({lat, lon}) => proj.fromLonLat([lon, lat]) )), }); feature.setId(segmentId); return feature; }); dataSource.addFeatures( stopPoints.concat(segmentLines) ); }); const makeBorderColor = mainColor => { const hsl = color(mainColor).hsl(); hsl.color = Math.max(0, hsl.color[2] -= 20); return hsl.hex(); }; const dataLayer = new VectorLayer({ source: dataSource, style: feature => { if (feature.get('type') === 'stop') { return new Style({ image: new Circle({ fill: new Fill({ color: feature.get('color'), }), stroke: new Stroke({ color: makeBorderColor(feature.get('color')), width: 2, }), radius: 6, }), }); } else if (feature.get('type') === 'segment') { return [ new Style({ stroke: new Stroke({ color: makeBorderColor(feature.get('color')), width: 8, }), }), new Style({ stroke: new Stroke({ color: feature.get('color'), width: 6, }), }), ]; } }, }); // Setup map const map = new Map({ target: 'map', layers: [ backgroundLayer, dataLayer, ], view: new View({ center: proj.fromLonLat([3.88, 43.605]), zoom: 13, maxZoom: 22, constrainResolution: true, }), }); module.exports = map;