tracktracker/src/front/map/network.js

131 lines
4.0 KiB
JavaScript

import network from "../../data/network.json";
import { cacheStyle, makeBorderColor, sizes } from "./common";
import GeoJSON from "ol/format/GeoJSON";
import VectorImageLayer from "ol/layer/VectorImage";
import VectorSource from "ol/source/Vector";
import { Style, Fill, Stroke, Circle } from "ol/style";
const geojsonReader = new GeoJSON({ featureProjection: "EPSG:3857" });
// Style used for the border of line segments
const segmentBorderStyle = cacheStyle(
color => new Style({
stroke: new Stroke({
color: makeBorderColor(color),
width: sizes.segmentOuter
})
}),
feature => feature.get("colors")[0],
);
// Style used for the inner part of line segments
const segmentInnerStyle = cacheStyle(
color => new Style({
stroke: new Stroke({
color,
width: sizes.segmentInner
})
}),
feature => feature.get("colors")[0],
);
// Style used for line stops
const stopStyle = cacheStyle(
color => new Style({
image: new Circle({
fill: new Fill({ color }),
stroke: new Stroke({
color: makeBorderColor(color),
width: sizes.stopBorder
}),
radius: sizes.stopRadius
})
}),
feature => feature.get("colors")[0],
);
/**
* Order for features related to a network line inside the same layer.
* @param {Feature} feature1 First feature to order.
* @param {Feature} feature2 Second feature to order.
* @returns {number} -1 if `feature1` comes before `feature2`, 1 if
* `feature2` comes before `feature1`, 0 if the order is irrelevant.
*/
const lineFeaturesOrder = (feature1, feature2) => {
// Place features with no lines attributed on the background
const lines1 = feature1.get("lines");
if (lines1.length === 0) {
return -1;
}
const lines2 = feature2.get("lines");
if (lines2.length === 0) {
return 1;
}
// Draw lines with a lower numeric value first
return Math.max(...lines2) - Math.max(...lines1);
};
/**
* Create the list of layers for displaying the transit network.
* @returns {Array.<Layer>} List of map layers.
*/
export const getLayers = () => {
const segmentsSource = new VectorSource();
const stopsSource = new VectorSource();
// Turn GeoJSON stops list and segments list into vector sources
const readFeatures = hash => Object.values(hash).map(json => {
json.properties.lines = json.properties.routes.filter(
// Only consider normal routes (excluding alternate routes)
([lineRef, routeRef]) =>
network.lines[lineRef].routes[routeRef].state === "normal"
).map(([lineRef]) => lineRef);
if (json.properties.lines.length >= 1) {
json.properties.colors = json.properties.lines.map(
lineRef => network.lines[lineRef].color
);
} else {
json.properties.colors = ["#FFFFFF"];
}
return geojsonReader.readFeature(json);
});
segmentsSource.addFeatures(readFeatures(network.segments));
stopsSource.addFeatures(readFeatures(network.stops));
// Background layer on which the darker borders of line segments are drawn
const segmentsBorderLayer = new VectorImageLayer({
source: segmentsSource,
renderOrder: lineFeaturesOrder,
style: segmentBorderStyle,
imageRatio: 2,
});
// Foreground layer on which the lighter inner part of line segments are
// drawn. The two layers are separated so that forks blend nicely together
const segmentsInnerLayer = new VectorImageLayer({
source: segmentsSource,
renderOrder: lineFeaturesOrder,
style: segmentInnerStyle,
imageRatio: 2,
});
const stopsLayer = new VectorImageLayer({
source: stopsSource,
renderOrder: lineFeaturesOrder,
style: stopStyle,
imageRatio: 2,
minZoom: 13,
});
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
};