131 lines
4.0 KiB
JavaScript
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];
|
|
};
|