From 2a216dd4e8f0907863f4fe60fafc626756f16093 Mon Sep 17 00:00:00 2001 From: James Lyne Date: Wed, 28 Jul 2021 02:14:20 +0100 Subject: [PATCH] Path performance improvements - Avoid intermediate objects when creating leaflet objects to reduce allocations - Make individual path objects non-reactive - Avoid projecting path points twice during updates --- src/leaflet/vector/LiveAtlasPolygon.ts | 10 ++++++---- src/leaflet/vector/LiveAtlasPolyline.ts | 12 ++++++++---- src/model/LiveAtlasProjection.ts | 24 ++++++++++++------------ src/providers/DynmapMapProvider.ts | 12 ++++++------ src/util/areas.ts | 10 +--------- src/util/circles.ts | 17 ++++------------- src/util/lines.ts | 12 +++--------- 7 files changed, 40 insertions(+), 57 deletions(-) diff --git a/src/leaflet/vector/LiveAtlasPolygon.ts b/src/leaflet/vector/LiveAtlasPolygon.ts index 2b2a24b..6179b83 100644 --- a/src/leaflet/vector/LiveAtlasPolygon.ts +++ b/src/leaflet/vector/LiveAtlasPolygon.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import {LatLngExpression, Polygon, PolylineOptions, Util} from "leaflet"; +import {LatLngExpression, Polygon, PolylineOptions} from "leaflet"; +import {LiveAtlasPath} from "@/index"; export interface LiveAtlasPolygonOptions extends PolylineOptions { minZoom?: number; @@ -22,8 +23,9 @@ export interface LiveAtlasPolygonOptions extends PolylineOptions { } export default class LiveAtlasPolygon extends Polygon { - constructor(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][], options?: LiveAtlasPolygonOptions) { - super(latlngs, options); - Util.setOptions(this, options); + declare options: LiveAtlasPolygonOptions; + + constructor(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][], options: LiveAtlasPath) { + super(latlngs, options.style); } } diff --git a/src/leaflet/vector/LiveAtlasPolyline.ts b/src/leaflet/vector/LiveAtlasPolyline.ts index c95b84f..41a8c0a 100644 --- a/src/leaflet/vector/LiveAtlasPolyline.ts +++ b/src/leaflet/vector/LiveAtlasPolyline.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import {LatLngExpression, Polyline, PolylineOptions, Util} from "leaflet"; +import {LatLngExpression, Polyline, PolylineOptions} from "leaflet"; +import {LiveAtlasPath} from "@/index"; export interface LiveAtlasPolylineOptions extends PolylineOptions { minZoom?: number; @@ -22,8 +23,11 @@ export interface LiveAtlasPolylineOptions extends PolylineOptions { } export default class LiveAtlasPolyline extends Polyline { - constructor(latlngs: LatLngExpression[] | LatLngExpression[][], options?: LiveAtlasPolylineOptions) { - super(latlngs, options); - Util.setOptions(this, options); + declare options: LiveAtlasPolylineOptions; + + constructor(latlngs: LatLngExpression[] | LatLngExpression[][], option: LiveAtlasPath) { + super(latlngs, option.style); + this.options.minZoom = option.minZoom; + this.options.maxZoom = option.maxZoom; } } diff --git a/src/model/LiveAtlasProjection.ts b/src/model/LiveAtlasProjection.ts index d8d6732..692e1a5 100644 --- a/src/model/LiveAtlasProjection.ts +++ b/src/model/LiveAtlasProjection.ts @@ -27,30 +27,30 @@ export interface LiveAtlasProjectionOptions { } export class LiveAtlasProjection { - private readonly options: LiveAtlasProjectionOptions + private readonly mapToWorld: [number, number, number, number, number, number, number, number, number]; + private readonly worldToMap: [number, number, number, number, number, number, number, number, number]; + private readonly nativeZoomLevels: number; constructor(options: LiveAtlasProjectionOptions) { - this.options = { - mapToWorld: options.mapToWorld || [0, 0, 0, 0, 0, 0, 0, 0], - worldToMap: options.worldToMap || [0, 0, 0, 0, 0, 0, 0, 0], - nativeZoomLevels: options.nativeZoomLevels || 1 - } + this.mapToWorld = options.mapToWorld || [0, 0, 0, 0, 0, 0, 0, 0]; + this.worldToMap = options.worldToMap || [0, 0, 0, 0, 0, 0, 0, 0]; + this.nativeZoomLevels = options.nativeZoomLevels || 1; } locationToLatLng(location: Coordinate): LatLng { - const wtp = this.options.worldToMap, + const wtp = this.worldToMap, lat = wtp[3] * location.x + wtp[4] * location.y + wtp[5] * location.z, lng = wtp[0] * location.x + wtp[1] * location.y + wtp[2] * location.z; return new LatLng( - -((128 - lat) / (1 << this.options.nativeZoomLevels)), - lng / (1 << this.options.nativeZoomLevels)); + -((128 - lat) / (1 << this.nativeZoomLevels)), + lng / (1 << this.nativeZoomLevels)); } latLngToLocation(latLng: LatLng, y: number): Coordinate { - const ptw = this.options.mapToWorld, - lat = latLng.lng * (1 << this.options.nativeZoomLevels), - lon = 128 + latLng.lat * (1 << this.options.nativeZoomLevels), + const ptw = this.mapToWorld, + lat = latLng.lng * (1 << this.nativeZoomLevels), + lon = 128 + latLng.lat * (1 << this.nativeZoomLevels), x = ptw[0] * lat + ptw[1] * lon + ptw[2] * y, z = ptw[6] * lat + ptw[7] * lon + ptw[8] * y; diff --git a/src/providers/DynmapMapProvider.ts b/src/providers/DynmapMapProvider.ts index e93338b..7fd7076 100644 --- a/src/providers/DynmapMapProvider.ts +++ b/src/providers/DynmapMapProvider.ts @@ -314,7 +314,7 @@ export default class DynmapMapProvider extends MapProvider { y: [number, number] = [area.ybottom || 0, area.ytop || 0], z = area.z || [0, 0]; - return { + return Object.seal({ style: { color: area.color || '#ff0000', opacity: area.opacity || 1, @@ -329,7 +329,7 @@ export default class DynmapMapProvider extends MapProvider { minZoom: typeof area.minzoom !== 'undefined' && area.minzoom > -1 ? area.minzoom : undefined, maxZoom: typeof area.maxzoom !== 'undefined' && area.maxzoom > -1 ? area.maxzoom : undefined, popupContent: area.desc || undefined, - }; + }); } private static buildLines(data: any): Map { @@ -347,7 +347,7 @@ export default class DynmapMapProvider extends MapProvider { } private static buildLine(line: any): LiveAtlasLine { - return { + return Object.seal({ style: { color: line.color || '#ff0000', opacity: line.opacity || 1, @@ -359,7 +359,7 @@ export default class DynmapMapProvider extends MapProvider { minZoom: typeof line.minzoom !== 'undefined' && line.minzoom > -1 ? line.minzoom : undefined, maxZoom: typeof line.maxzoom !== 'undefined' && line.maxzoom > -1 ? line.maxzoom : undefined, popupContent: line.desc || undefined, - }; + }); } private static buildCircles(data: any): Map { @@ -377,7 +377,7 @@ export default class DynmapMapProvider extends MapProvider { } private static buildCircle(circle: any): LiveAtlasCircle { - return { + return Object.seal({ location: { x: circle.x || 0, y: circle.y || 0, @@ -397,7 +397,7 @@ export default class DynmapMapProvider extends MapProvider { minZoom: typeof circle.minzoom !== 'undefined' && circle.minzoom > -1 ? circle.minzoom : undefined, maxZoom: typeof circle.maxzoom !== 'undefined' && circle.maxzoom > -1 ? circle.maxzoom : undefined, popupContent: circle.desc || undefined, - }; + }); } private buildUpdates(data: Array) { diff --git a/src/util/areas.ts b/src/util/areas.ts index 515dcb5..53e4ce8 100644 --- a/src/util/areas.ts +++ b/src/util/areas.ts @@ -25,15 +25,7 @@ import {Coordinate, LiveAtlasArea} from "@/index"; export const createArea = (options: LiveAtlasArea, converter: Function): LiveAtlasPolyline | LiveAtlasPolygon => { const outline = !options.style.fillOpacity || (options.style.fillOpacity <= 0), points = options.points.map(projectPointsMapCallback, converter) as LatLngExpression[] | LatLngExpression[][], - area = outline ? new LiveAtlasPolyline(points, { - ...options.style, - minZoom: options.minZoom, - maxZoom: options.maxZoom, - }) : new LiveAtlasPolygon(points, { - ...options.style, - minZoom: options.minZoom, - maxZoom: options.maxZoom, - }); + area = outline ? new LiveAtlasPolyline(points, options) : new LiveAtlasPolygon(points, options); if (options.label) { area.bindPopup(() => createPopup(options)); diff --git a/src/util/circles.ts b/src/util/circles.ts index 8388fd7..51f27e4 100644 --- a/src/util/circles.ts +++ b/src/util/circles.ts @@ -25,15 +25,7 @@ import {LiveAtlasCircle} from "@/index"; export const createCircle = (options: LiveAtlasCircle, converter: Function): LiveAtlasPolyline | LiveAtlasPolygon => { const outline = !options.style.fillOpacity || (options.style.fillOpacity <= 0), points = getCirclePoints(options, converter, outline), - circle = outline ? new LiveAtlasPolyline(points, { - ...options.style, - minZoom: options.minZoom, - maxZoom: options.maxZoom, - }) : new LiveAtlasPolygon(points, { - ...options.style, - minZoom: options.minZoom, - maxZoom: options.maxZoom, - }); + circle = outline ? new LiveAtlasPolyline(points, options) : new LiveAtlasPolygon(points, options); if(options.label) { circle.bindPopup(() => createPopup(options)); @@ -43,18 +35,17 @@ export const createCircle = (options: LiveAtlasCircle, converter: Function): Liv }; export const updateCircle = (circle: LiveAtlasPolyline | LiveAtlasPolygon | undefined, options: LiveAtlasCircle, converter: Function): LiveAtlasPolyline | LiveAtlasPolygon => { - const outline = (options.style && options.style.fillOpacity && (options.style.fillOpacity <= 0)) as boolean, - points = getCirclePoints(options, converter, outline); - if (!circle) { return createCircle(options, converter); } + const outline = (options.style && options.style.fillOpacity && (options.style.fillOpacity <= 0)) as boolean; + circle.closePopup(); circle.unbindPopup(); circle.bindPopup(() => createPopup(options)); circle.setStyle(options.style); - circle.setLatLngs(points); + circle.setLatLngs(getCirclePoints(options, converter, outline)); circle.redraw(); return circle; diff --git a/src/util/lines.ts b/src/util/lines.ts index 0aefb3d..cd1ad02 100644 --- a/src/util/lines.ts +++ b/src/util/lines.ts @@ -22,12 +22,8 @@ import {Coordinate, LiveAtlasLine} from "@/index"; import {LatLngExpression} from "leaflet"; export const createLine = (options: LiveAtlasLine, converter: Function): LiveAtlasPolyline => { - const points = options.points.map(projectPointsMapCallback, converter) as LatLngExpression[], - line = new LiveAtlasPolyline(points, { - ...options.style, - minZoom: options.minZoom, - maxZoom: options.maxZoom, - }); + const points = options.points.map(projectPointsMapCallback, converter), + line = new LiveAtlasPolyline(points, options); if(options.label) { line.bindPopup(() => createPopup(options)); @@ -37,8 +33,6 @@ export const createLine = (options: LiveAtlasLine, converter: Function): LiveAtl }; export const updateLine = (line: LiveAtlasPolyline | undefined, options: LiveAtlasLine, converter: Function): LiveAtlasPolyline => { - const points = options.points.map(projectPointsMapCallback, converter); - if (!line) { return createLine(options, converter); } @@ -47,7 +41,7 @@ export const updateLine = (line: LiveAtlasPolyline | undefined, options: LiveAtl line.unbindPopup(); line.bindPopup(() => createPopup(options)); line.setStyle(options.style); - line.setLatLngs(points); + line.setLatLngs(options.points.map(projectPointsMapCallback, converter)); line.redraw(); return line;