Improve front rendering performance
This commit is contained in:
parent
05d7faa725
commit
7465314a12
|
@ -18,6 +18,26 @@ export const makeCourseColor = mainColor => {
|
|||
return color(mainColor).lighten(0.2).hex();
|
||||
};
|
||||
|
||||
/**
|
||||
* Make an OpenLayers style function cache its results.
|
||||
* @param {Function} createStyle Create a style based on the cache key value.
|
||||
* @param {Function} [cacheKey] Return the cache key for each feature
|
||||
* (default: identity function).
|
||||
* @return {Function} Style function that caches the generated styles.
|
||||
*/
|
||||
export const cacheStyle = (createStyle, cacheKey = x => x) => {
|
||||
const cache = {};
|
||||
return (feature) => {
|
||||
const key = cacheKey(feature);
|
||||
|
||||
if (!(key in cache)) {
|
||||
cache[key] = createStyle(key);
|
||||
}
|
||||
|
||||
return cache[key];
|
||||
};
|
||||
};
|
||||
|
||||
export const sizes = {
|
||||
segmentOuter: 8,
|
||||
segmentInner: 6,
|
||||
|
|
|
@ -3,17 +3,16 @@ import "ol/ol.css";
|
|||
import { Map, View } from "ol";
|
||||
import { getVectorContext } from "ol/render";
|
||||
import Point from "ol/geom/Point";
|
||||
import { fromExtent } from 'ol/geom/Polygon';
|
||||
import * as proj from "ol/proj";
|
||||
import { Style, Icon } from "ol/style";
|
||||
import * as tilesLayers from "./tiles";
|
||||
import * as networkLayers from "./network";
|
||||
import { sizes, makeBorderColor, makeCourseColor } from "./common";
|
||||
import { sizes, cacheStyle, makeBorderColor, makeCourseColor } from "./common";
|
||||
import network from "../../tam/network.json";
|
||||
|
||||
const courseStyles = {};
|
||||
|
||||
const getCourseStyle = lineColor => {
|
||||
if (!(lineColor in courseStyles)) {
|
||||
const courseStyle = cacheStyle(
|
||||
lineColor => {
|
||||
const icon = window.document.createElement("canvas");
|
||||
|
||||
const shapeSize = sizes.courseSize;
|
||||
|
@ -47,16 +46,14 @@ const getCourseStyle = lineColor => {
|
|||
iconCtx.fill();
|
||||
}
|
||||
|
||||
courseStyles[lineColor] = new Style({
|
||||
return new Style({
|
||||
image: new Icon({
|
||||
img: icon,
|
||||
imgSize: [icon.width, icon.height]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return courseStyles[lineColor];
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export const create = (target, coursesSimulation, onClick) => {
|
||||
const view = new View({
|
||||
|
@ -96,11 +93,17 @@ export const create = (target, coursesSimulation, onClick) => {
|
|||
/* eslint-enable no-underscore-dangle */
|
||||
|
||||
const ctx = getVectorContext(ev);
|
||||
const bbox = fromExtent(map.getView().calculateExtent());
|
||||
bbox.scale(1.05);
|
||||
|
||||
for (const course of Object.values(coursesSimulation.courses)) {
|
||||
if (!bbox.intersectsCoordinate(course.position)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const point = new Point(course.position);
|
||||
const color = network.lines[course.line].color;
|
||||
const style = getCourseStyle(color);
|
||||
const style = courseStyle(color);
|
||||
|
||||
style.getImage().setRotation(
|
||||
view.getRotation() +
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import network from "../../tam/network.json";
|
||||
import { makeBorderColor, sizes } from "./common";
|
||||
import { cacheStyle, makeBorderColor, sizes } from "./common";
|
||||
|
||||
import GeoJSON from "ol/format/GeoJSON";
|
||||
import VectorLayer from "ol/layer/Vector";
|
||||
import VectorImageLayer from "ol/layer/VectorImage";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
|
||||
import { Style, Fill, Stroke, Circle } from "ol/style";
|
||||
|
@ -10,34 +10,41 @@ 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 = feature => new Style({
|
||||
const segmentBorderStyle = cacheStyle(
|
||||
color => new Style({
|
||||
stroke: new Stroke({
|
||||
color: makeBorderColor(feature.get("colors")[0]),
|
||||
color: makeBorderColor(color),
|
||||
width: sizes.segmentOuter
|
||||
})
|
||||
});
|
||||
}),
|
||||
feature => feature.get("colors")[0],
|
||||
);
|
||||
|
||||
// Style used for the inner part of line segments
|
||||
const segmentInnerStyle = feature => new Style({
|
||||
const segmentInnerStyle = cacheStyle(
|
||||
color => new Style({
|
||||
stroke: new Stroke({
|
||||
color: feature.get("colors")[0],
|
||||
color,
|
||||
width: sizes.segmentInner
|
||||
})
|
||||
});
|
||||
}),
|
||||
feature => feature.get("colors")[0],
|
||||
);
|
||||
|
||||
// Style used for line stops
|
||||
const stopStyle = feature => new Style({
|
||||
const stopStyle = cacheStyle(
|
||||
color => new Style({
|
||||
image: new Circle({
|
||||
fill: new Fill({
|
||||
color: feature.get("colors")[0]
|
||||
}),
|
||||
fill: new Fill({ color }),
|
||||
stroke: new Stroke({
|
||||
color: makeBorderColor(feature.get("colors")[0]),
|
||||
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.
|
||||
|
@ -75,7 +82,6 @@ export const getLayers = () => {
|
|||
// 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"
|
||||
|
@ -96,34 +102,28 @@ export const getLayers = () => {
|
|||
stopsSource.addFeatures(readFeatures(network.stops));
|
||||
|
||||
// Background layer on which the darker borders of line segments are drawn
|
||||
const segmentsBorderLayer = new VectorLayer({
|
||||
const segmentsBorderLayer = new VectorImageLayer({
|
||||
source: segmentsSource,
|
||||
renderOrder: lineFeaturesOrder,
|
||||
style: segmentBorderStyle,
|
||||
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true
|
||||
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 VectorLayer({
|
||||
const segmentsInnerLayer = new VectorImageLayer({
|
||||
source: segmentsSource,
|
||||
renderOrder: lineFeaturesOrder,
|
||||
style: segmentInnerStyle,
|
||||
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true
|
||||
imageRatio: 2,
|
||||
});
|
||||
|
||||
const stopsLayer = new VectorLayer({
|
||||
const stopsLayer = new VectorImageLayer({
|
||||
source: stopsSource,
|
||||
renderOrder: lineFeaturesOrder,
|
||||
style: stopStyle,
|
||||
|
||||
imageRatio: 2,
|
||||
minZoom: 13,
|
||||
updateWhileInteracting: true,
|
||||
updateWhileAnimating: true
|
||||
});
|
||||
|
||||
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
|
||||
|
|
Loading…
Reference in New Issue