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();
|
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 = {
|
export const sizes = {
|
||||||
segmentOuter: 8,
|
segmentOuter: 8,
|
||||||
segmentInner: 6,
|
segmentInner: 6,
|
||||||
|
|
|
@ -3,17 +3,16 @@ import "ol/ol.css";
|
||||||
import { Map, View } from "ol";
|
import { Map, View } from "ol";
|
||||||
import { getVectorContext } from "ol/render";
|
import { getVectorContext } from "ol/render";
|
||||||
import Point from "ol/geom/Point";
|
import Point from "ol/geom/Point";
|
||||||
|
import { fromExtent } from 'ol/geom/Polygon';
|
||||||
import * as proj from "ol/proj";
|
import * as proj from "ol/proj";
|
||||||
import { Style, Icon } from "ol/style";
|
import { Style, Icon } from "ol/style";
|
||||||
import * as tilesLayers from "./tiles";
|
import * as tilesLayers from "./tiles";
|
||||||
import * as networkLayers from "./network";
|
import * as networkLayers from "./network";
|
||||||
import { sizes, makeBorderColor, makeCourseColor } from "./common";
|
import { sizes, cacheStyle, makeBorderColor, makeCourseColor } from "./common";
|
||||||
import network from "../../tam/network.json";
|
import network from "../../tam/network.json";
|
||||||
|
|
||||||
const courseStyles = {};
|
const courseStyle = cacheStyle(
|
||||||
|
lineColor => {
|
||||||
const getCourseStyle = lineColor => {
|
|
||||||
if (!(lineColor in courseStyles)) {
|
|
||||||
const icon = window.document.createElement("canvas");
|
const icon = window.document.createElement("canvas");
|
||||||
|
|
||||||
const shapeSize = sizes.courseSize;
|
const shapeSize = sizes.courseSize;
|
||||||
|
@ -47,16 +46,14 @@ const getCourseStyle = lineColor => {
|
||||||
iconCtx.fill();
|
iconCtx.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
courseStyles[lineColor] = new Style({
|
return new Style({
|
||||||
image: new Icon({
|
image: new Icon({
|
||||||
img: icon,
|
img: icon,
|
||||||
imgSize: [icon.width, icon.height]
|
imgSize: [icon.width, icon.height]
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
);
|
||||||
return courseStyles[lineColor];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const create = (target, coursesSimulation, onClick) => {
|
export const create = (target, coursesSimulation, onClick) => {
|
||||||
const view = new View({
|
const view = new View({
|
||||||
|
@ -96,11 +93,17 @@ export const create = (target, coursesSimulation, onClick) => {
|
||||||
/* eslint-enable no-underscore-dangle */
|
/* eslint-enable no-underscore-dangle */
|
||||||
|
|
||||||
const ctx = getVectorContext(ev);
|
const ctx = getVectorContext(ev);
|
||||||
|
const bbox = fromExtent(map.getView().calculateExtent());
|
||||||
|
bbox.scale(1.05);
|
||||||
|
|
||||||
for (const course of Object.values(coursesSimulation.courses)) {
|
for (const course of Object.values(coursesSimulation.courses)) {
|
||||||
|
if (!bbox.intersectsCoordinate(course.position)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const point = new Point(course.position);
|
const point = new Point(course.position);
|
||||||
const color = network.lines[course.line].color;
|
const color = network.lines[course.line].color;
|
||||||
const style = getCourseStyle(color);
|
const style = courseStyle(color);
|
||||||
|
|
||||||
style.getImage().setRotation(
|
style.getImage().setRotation(
|
||||||
view.getRotation() +
|
view.getRotation() +
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import network from "../../tam/network.json";
|
import network from "../../tam/network.json";
|
||||||
import { makeBorderColor, sizes } from "./common";
|
import { cacheStyle, makeBorderColor, sizes } from "./common";
|
||||||
|
|
||||||
import GeoJSON from "ol/format/GeoJSON";
|
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 VectorSource from "ol/source/Vector";
|
||||||
|
|
||||||
import { Style, Fill, Stroke, Circle } from "ol/style";
|
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" });
|
const geojsonReader = new GeoJSON({ featureProjection: "EPSG:3857" });
|
||||||
|
|
||||||
// Style used for the border of line segments
|
// Style used for the border of line segments
|
||||||
const segmentBorderStyle = feature => new Style({
|
const segmentBorderStyle = cacheStyle(
|
||||||
|
color => new Style({
|
||||||
stroke: new Stroke({
|
stroke: new Stroke({
|
||||||
color: makeBorderColor(feature.get("colors")[0]),
|
color: makeBorderColor(color),
|
||||||
width: sizes.segmentOuter
|
width: sizes.segmentOuter
|
||||||
})
|
})
|
||||||
});
|
}),
|
||||||
|
feature => feature.get("colors")[0],
|
||||||
|
);
|
||||||
|
|
||||||
// Style used for the inner part of line segments
|
// Style used for the inner part of line segments
|
||||||
const segmentInnerStyle = feature => new Style({
|
const segmentInnerStyle = cacheStyle(
|
||||||
|
color => new Style({
|
||||||
stroke: new Stroke({
|
stroke: new Stroke({
|
||||||
color: feature.get("colors")[0],
|
color,
|
||||||
width: sizes.segmentInner
|
width: sizes.segmentInner
|
||||||
})
|
})
|
||||||
});
|
}),
|
||||||
|
feature => feature.get("colors")[0],
|
||||||
|
);
|
||||||
|
|
||||||
// Style used for line stops
|
// Style used for line stops
|
||||||
const stopStyle = feature => new Style({
|
const stopStyle = cacheStyle(
|
||||||
|
color => new Style({
|
||||||
image: new Circle({
|
image: new Circle({
|
||||||
fill: new Fill({
|
fill: new Fill({ color }),
|
||||||
color: feature.get("colors")[0]
|
|
||||||
}),
|
|
||||||
stroke: new Stroke({
|
stroke: new Stroke({
|
||||||
color: makeBorderColor(feature.get("colors")[0]),
|
color: makeBorderColor(color),
|
||||||
width: sizes.stopBorder
|
width: sizes.stopBorder
|
||||||
}),
|
}),
|
||||||
radius: sizes.stopRadius
|
radius: sizes.stopRadius
|
||||||
})
|
})
|
||||||
});
|
}),
|
||||||
|
feature => feature.get("colors")[0],
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order for features related to a network line inside the same layer.
|
* 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
|
// Turn GeoJSON stops list and segments list into vector sources
|
||||||
const readFeatures = hash => Object.values(hash).map(json => {
|
const readFeatures = hash => Object.values(hash).map(json => {
|
||||||
json.properties.lines = json.properties.routes.filter(
|
json.properties.lines = json.properties.routes.filter(
|
||||||
|
|
||||||
// Only consider normal routes (excluding alternate routes)
|
// Only consider normal routes (excluding alternate routes)
|
||||||
([lineRef, routeRef]) =>
|
([lineRef, routeRef]) =>
|
||||||
network.lines[lineRef].routes[routeRef].state === "normal"
|
network.lines[lineRef].routes[routeRef].state === "normal"
|
||||||
|
@ -96,34 +102,28 @@ export const getLayers = () => {
|
||||||
stopsSource.addFeatures(readFeatures(network.stops));
|
stopsSource.addFeatures(readFeatures(network.stops));
|
||||||
|
|
||||||
// Background layer on which the darker borders of line segments are drawn
|
// Background layer on which the darker borders of line segments are drawn
|
||||||
const segmentsBorderLayer = new VectorLayer({
|
const segmentsBorderLayer = new VectorImageLayer({
|
||||||
source: segmentsSource,
|
source: segmentsSource,
|
||||||
renderOrder: lineFeaturesOrder,
|
renderOrder: lineFeaturesOrder,
|
||||||
style: segmentBorderStyle,
|
style: segmentBorderStyle,
|
||||||
|
imageRatio: 2,
|
||||||
updateWhileInteracting: true,
|
|
||||||
updateWhileAnimating: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Foreground layer on which the lighter inner part of line segments are
|
// Foreground layer on which the lighter inner part of line segments are
|
||||||
// drawn. The two layers are separated so that forks blend nicely together
|
// drawn. The two layers are separated so that forks blend nicely together
|
||||||
const segmentsInnerLayer = new VectorLayer({
|
const segmentsInnerLayer = new VectorImageLayer({
|
||||||
source: segmentsSource,
|
source: segmentsSource,
|
||||||
renderOrder: lineFeaturesOrder,
|
renderOrder: lineFeaturesOrder,
|
||||||
style: segmentInnerStyle,
|
style: segmentInnerStyle,
|
||||||
|
imageRatio: 2,
|
||||||
updateWhileInteracting: true,
|
|
||||||
updateWhileAnimating: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const stopsLayer = new VectorLayer({
|
const stopsLayer = new VectorImageLayer({
|
||||||
source: stopsSource,
|
source: stopsSource,
|
||||||
renderOrder: lineFeaturesOrder,
|
renderOrder: lineFeaturesOrder,
|
||||||
style: stopStyle,
|
style: stopStyle,
|
||||||
|
imageRatio: 2,
|
||||||
minZoom: 13,
|
minZoom: 13,
|
||||||
updateWhileInteracting: true,
|
|
||||||
updateWhileAnimating: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
|
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
|
||||||
|
|
Loading…
Reference in New Issue