Better blending of adjacent lines on map

This commit is contained in:
Mattéo Delabre 2020-07-17 19:59:34 +02:00
parent a5aa58d2ee
commit 37a9a1bd72
Signed by: matteo
GPG Key ID: AE3FBD02DC583ABB
1 changed files with 77 additions and 67 deletions

View File

@ -1,5 +1,6 @@
require('ol/ol.css'); require('ol/ol.css');
const axios = require('axios');
const {Map, View} = require('ol'); const {Map, View} = require('ol');
const TileLayer = require('ol/layer/Tile').default; const TileLayer = require('ol/layer/Tile').default;
@ -17,47 +18,77 @@ const proj = require('ol/proj');
const {Style, Fill, Stroke, Circle} = require('ol/style'); const {Style, Fill, Stroke, Circle} = require('ol/style');
const color = require('color'); const color = require('color');
const mapboxToken = 'pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJjazUxaWNsdXcwdWhjM2\ const mapboxToken = `pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\
9tc2xndXJoNGtxIn0.xELwMerqJLFimIqU6RxnZw'; h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw`;
const server = window.origin; const server = window.origin;
const fetchDataSources = async () => const fetchDataSources = async () =>
{ {
const dataSource = new VectorSource(); const segmentsSource = new VectorSource();
const stopsSource = new VectorSource();
const res = await fetch(`${server}/network`); const network = (await axios.get(`${server}/network`)).data;
const network = await res.json();
const stopPoints = Object.entries(network.stops) segmentsSource.addFeatures(
.map(([stopId, stop]) => Object.values(network.lines).flatMap(({color, routes}) =>
new Feature({
type: 'stop',
color: network.lines[stop.lines[0]].color,
geometry: new Point(proj.fromLonLat([stop.lon, stop.lat])),
})
);
dataSource.addFeatures(stopPoints);
const segmentLines = Object.values(network.lines)
.flatMap(({color, routes}) =>
routes.map(({segments}) => routes.map(({segments}) =>
new Feature({ new Feature({
type: 'segment',
color, color,
geometry: new LineString(segments.flat().map( geometry: new LineString(segments.flat().map(
({lat, lon}) => proj.fromLonLat([lon, lat]) ({lat, lon}) => proj.fromLonLat([lon, lat])
)), )),
}) })
) )
); )
);
dataSource.addFeatures(segmentLines); stopsSource.addFeatures(
Object.entries(network.stops).map(([stopId, stop]) =>
new Feature({
color: network.lines[stop.lines[0]].color,
geometry: new Point(proj.fromLonLat([stop.lon, stop.lat])),
})
)
);
return dataSource; return {segmentsSource, stopsSource};
}; };
const makeBorderColor = mainColor =>
{
const hsl = color(mainColor).hsl();
hsl.color = Math.max(0, hsl.color[2] -= 20);
return hsl.hex();
};
const segmentsBorderStyle = feature => new Style({
stroke: new Stroke({
color: makeBorderColor(feature.get('color')),
width: 8,
}),
});
const segmentsInnerStyle = feature => new Style({
stroke: new Stroke({
color: feature.get('color'),
width: 6,
}),
});
const stopsStyle = feature => new Style({
image: new Circle({
fill: new Fill({
color: feature.get('color'),
}),
stroke: new Stroke({
color: makeBorderColor(feature.get('color')),
width: 1.5,
}),
radius: 6,
}),
});
const createMap = async (target) => const createMap = async (target) =>
{ {
// Map background // Map background
@ -74,54 +105,31 @@ const createMap = async (target) =>
}); });
// Data overlay // Data overlay
const dataSource = await fetchDataSources(); const {segmentsSource, stopsSource} = await fetchDataSources();
const makeBorderColor = mainColor => const segmentsBorderLayer = new VectorLayer({
{ source: segmentsSource,
const hsl = color(mainColor).hsl(); style: segmentsBorderStyle,
hsl.color = Math.max(0, hsl.color[2] -= 20);
return hsl.hex();
};
const dataLayer = new VectorLayer({
source: dataSource,
updateWhileInteracting: true, updateWhileInteracting: true,
updateWhileAnimating: true, updateWhileAnimating: true,
style: feature => });
{
if (feature.get('type') === 'stop') const segmentsInnerLayer = new VectorLayer({
{ source: segmentsSource,
return new Style({ style: segmentsInnerStyle,
image: new Circle({
fill: new Fill({ updateWhileInteracting: true,
color: feature.get('color'), updateWhileAnimating: true,
}), });
stroke: new Stroke({
color: makeBorderColor(feature.get('color')), const stopsLayer = new VectorLayer({
width: 2, source: stopsSource,
}), style: stopsStyle,
radius: 6,
}), minZoom: 13,
}); updateWhileInteracting: true,
} updateWhileAnimating: true,
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 // Setup map
@ -129,7 +137,9 @@ const createMap = async (target) =>
target, target,
layers: [ layers: [
backgroundLayer, backgroundLayer,
dataLayer, segmentsBorderLayer,
segmentsInnerLayer,
stopsLayer,
], ],
view: new View({ view: new View({
center: proj.fromLonLat([3.88, 43.605]), center: proj.fromLonLat([3.88, 43.605]),