From 5fb0a3e2f4762f2d96f74999bbbe79fc79c67fbe Mon Sep 17 00:00:00 2001 From: James Lyne Date: Sun, 25 Jul 2021 03:23:29 +0100 Subject: [PATCH] Move night/update handling into DynmapTileLayer --- src/components/map/layer/MapLayer.vue | 46 +------------- src/leaflet/tileLayer/DynmapTileLayer.ts | 78 ++++++++++++++++++++---- 2 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/components/map/layer/MapLayer.vue b/src/components/map/layer/MapLayer.vue index 17d1931..1326053 100644 --- a/src/components/map/layer/MapLayer.vue +++ b/src/components/map/layer/MapLayer.vue @@ -18,8 +18,6 @@ import {defineComponent, onUnmounted, computed, watch} from "@vue/runtime-core"; import {Map} from 'leaflet'; import {useStore} from "@/store"; -import {ActionTypes} from "@/store/action-types"; -import {getMinecraftTime} from "@/util"; import {DynmapTileLayer} from "@/leaflet/tileLayer/DynmapTileLayer"; import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition"; @@ -40,58 +38,22 @@ export default defineComponent({ }, setup(props) { - let updateFrame = 0, - stopUpdateWatch: Function; - const store = useStore(), - night = computed(() => getMinecraftTime(store.state.currentWorldState.timeOfDay).night), layer = new DynmapTileLayer({ errorTileUrl: 'images/blank.png', mapSettings: Object.freeze(JSON.parse(JSON.stringify(props.map))), - night: night.value, }), - pendingUpdates = computed(() => !!store.state.pendingTileUpdates.length), - active = computed(() => props.map === store.state.currentMap), + active = computed(() => props.map === store.state.currentMap); - enableLayer = () => { + const enableLayer = () => { props.leaflet.addLayer(layer); - - stopUpdateWatch = watch(pendingUpdates, (newValue, oldValue) => { - if(newValue && !oldValue && !updateFrame) { - handlePendingUpdates(); - } - }); }, disableLayer = () => { layer.remove(); - - if(stopUpdateWatch) { - stopUpdateWatch(); - } - }, - - handlePendingUpdates = async () => { - const updates = await useStore().dispatch(ActionTypes.POP_TILE_UPDATES, 10); - - for(const update of updates) { - layer.updateNamedTile(update.name, update.timestamp); - } - - if(pendingUpdates.value) { - // eslint-disable-next-line no-unused-vars - updateFrame = requestAnimationFrame(() => handlePendingUpdates()); - } else { - updateFrame = 0; - } }; watch(active, (newValue) => newValue ? enableLayer() : disableLayer()); - watch(night, (newValue) => { - if(props.map.nightAndDay) { - layer.setNight(newValue); - } - }); if(active.value) { enableLayer(); @@ -99,10 +61,6 @@ export default defineComponent({ onUnmounted(() => { disableLayer(); - - if(updateFrame) { - cancelAnimationFrame(updateFrame); - } }); }, diff --git a/src/leaflet/tileLayer/DynmapTileLayer.ts b/src/leaflet/tileLayer/DynmapTileLayer.ts index 6dd66ae..9de6574 100644 --- a/src/leaflet/tileLayer/DynmapTileLayer.ts +++ b/src/leaflet/tileLayer/DynmapTileLayer.ts @@ -17,10 +17,14 @@ * limitations under the License. */ -import {TileLayer, Coords, DoneCallback, TileLayerOptions, DomUtil, Util} from 'leaflet'; -import {store} from "@/store"; +import {Coords, DoneCallback, DomUtil, TileLayerOptions, TileLayer, Util} from 'leaflet'; +import {useStore} from "@/store"; import {Coordinate} from "@/index"; import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition"; +import {computed, watch} from "@vue/runtime-core"; +import {ComputedRef} from "@vue/reactivity"; +import {WatchStopHandle} from "vue"; +import {ActionTypes} from "@/store/action-types"; export interface DynmapTileLayerOptions extends TileLayerOptions { mapSettings: LiveAtlasMapDefinition; @@ -54,6 +58,8 @@ export interface TileInfo { fmt: string; } +const store = useStore(); + // noinspection JSUnusedGlobalSymbols export class DynmapTileLayer extends TileLayer { private readonly _mapSettings: LiveAtlasMapDefinition; @@ -63,7 +69,15 @@ export class DynmapTileLayer extends TileLayer { private readonly _loadingTiles: Set = Object.seal(new Set()); private readonly _tileTemplate: DynmapTileElement; private readonly _baseUrl: string; - declare readonly options: DynmapTileLayerOptions; + + private readonly _night: ComputedRef; + private readonly _pendingUpdates: ComputedRef; + private readonly _nightUnwatch: WatchStopHandle; + private readonly _updateUnwatch: WatchStopHandle; + private _updateFrame: number = 0; + + // @ts-ignore + declare options: DynmapTileLayerOptions; constructor(options: DynmapTileLayerOptions) { super('', options); @@ -93,9 +107,23 @@ export class DynmapTileLayer extends TileLayer { if(this.options.crossOrigin || this.options.crossOrigin === '') { this._tileTemplate.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; } + + this._pendingUpdates = computed(() => !!store.state.pendingTileUpdates.length); + this._updateUnwatch = watch(this._pendingUpdates, (newValue, oldValue) => { + if(newValue && !oldValue && !this._updateFrame) { + this.handlePendingUpdates(); + } + }); + + this._night = computed(() => store.getters.night); + this._nightUnwatch = watch(this._night, () => { + if(this._mapSettings.nightAndDay) { + this.redraw(); + } + }); } - getTileName(coords: Coordinate) { + private getTileName(coords: Coordinate) { const info = this.getTileInfo(coords); // Y is inverted for HD-map. info.y = -info.y; @@ -107,7 +135,7 @@ export class DynmapTileLayer extends TileLayer { return this.getTileUrlFromName(this.getTileName(coords)); } - getTileUrlFromName(name: string, timestamp?: number) { + private getTileUrlFromName(name: string, timestamp?: number) { let url = this._cachedTileUrls.get(name); if (!url) { @@ -124,7 +152,7 @@ export class DynmapTileLayer extends TileLayer { return url; } - updateNamedTile(name: string, timestamp: number) { + private updateNamedTile(name: string, timestamp: number) { const tile = this._namedTiles.get(name); this._cachedTileUrls.delete(name); @@ -231,14 +259,14 @@ export class DynmapTileLayer extends TileLayer { } // Some helper functions. - zoomprefix(amount: number) { + private zoomprefix(amount: number) { // amount == 0 -> '' // amount == 1 -> 'z_' // amount == 2 -> 'zz_' return 'z'.repeat(amount) + (amount === 0 ? '' : '_'); } - getTileInfo(coords: Coordinate): TileInfo { + private getTileInfo(coords: Coordinate): TileInfo { // zoom: max zoomed in = this.options.maxZoom, max zoomed out = 0 // izoom: max zoomed in = 0, max zoomed out = this.options.maxZoom // zoomoutlevel: izoom < mapzoomin -> 0, else -> izoom - mapzoomin (which ranges from 0 till mapzoomout) @@ -250,7 +278,7 @@ export class DynmapTileLayer extends TileLayer { return { prefix: this._mapSettings.prefix, - nightday: (this._mapSettings.nightAndDay && !this.options.night) ? '_day' : '', + nightday: (this._mapSettings.nightAndDay && !this._night.value) ? '_day' : '', scaledx: x >> 5, scaledy: y >> 5, zoom: this.zoomprefix(zoomoutlevel), @@ -261,10 +289,34 @@ export class DynmapTileLayer extends TileLayer { }; } - setNight(night: boolean) { - if(this.options.night !== night) { - this.options.night = night; - this.redraw(); + private async handlePendingUpdates() { + const updates = await store.dispatch(ActionTypes.POP_TILE_UPDATES, 10); + + for(const update of updates) { + this.updateNamedTile(update.name, update.timestamp); + } + + if(this._pendingUpdates.value) { + // eslint-disable-next-line no-unused-vars + this._updateFrame = requestAnimationFrame(() => this.handlePendingUpdates()); + } else { + this._updateFrame = 0; } } + + remove() { + super.remove(); + + this._nightUnwatch(); + + if(this._updateFrame) { + cancelAnimationFrame(this._updateFrame); + } + + if(this._updateUnwatch) { + this._updateUnwatch(); + } + + return this; + } }