Migrate LoadingControl to vue
This commit is contained in:
parent
7471bb794f
commit
318ccf6e33
4
.idea/scopes/Original.xml
generated
4
.idea/scopes/Original.xml
generated
@ -1,3 +1,3 @@
|
|||||||
<component name="DependencyValidationManager">
|
<component name="DependencyValidationManager">
|
||||||
<scope name="Original" pattern="!file:src/leaflet/control/ClockControl.ts&&!file:src/leaflet/control/CoordinatesControl.ts&&!file:src/leaflet/control/LinkControl.ts&&!file:src/leaflet/control/LogoControl.ts&&!file:src/leaflet/icon/PlayerIcon.ts&&!file:src/leaflet/icon/GenericIcon.ts&&!file:src/leaflet/tileLayer/DynmapTileLayer.ts&&!file:src/util/areas.ts&&!file:src/util/circles.ts&&!file:src/util/lines.ts&&!file:src/util/markers.ts&&!file[LiveAtlas]:standalone/*&&!file:src/model/LiveAtlasProjection.ts&&!file:src/leaflet/control/LiveAtlasLayerControl.ts&&!file[LiveAtlas]:patches/*&&!file[LiveAtlas]:public/*&&!file[LiveAtlas]:.idea/*&&!file[LiveAtlas]:.idea//*&&!file[LiveAtlas]:patches//*&&!file[LiveAtlas]:public//*&&!file[LiveAtlas]:standalone//*&&!file:FUNDING.yml&&!file:README.md&&!file:tsconfig.json&&!file:.gitignore&&!file:.env&&!file:LICENSE.md&&!file:package-lock.json&&!file:package.json&&!file:vite.config.ts&&!file:index.html&&!file:src/leaflet/control/LoadingControl.ts&&!file:src/scss/style.scss&&!file[LiveAtlas]:src/assets/icons//*&&!file:src/providers/OverviewerMapProvider.ts&&!file:src/providers/DynmapMapProvider.ts&&!file:src/leaflet/projection/OverviewerProjection.ts&&!file:src/leaflet/tileLayer/OverviewerTileLayer.ts&&!file:jest.config.ts&&!file:.npmignore&&!file:plugin.yml&&!file[LiveAtlas]:java/*&&!file[LiveAtlas]:java//*" />
|
<scope name="Original" pattern="!file:src/leaflet/control/ClockControl.ts&&!file:src/leaflet/control/CoordinatesControl.ts&&!file:src/leaflet/control/LinkControl.ts&&!file:src/leaflet/control/LogoControl.ts&&!file:src/leaflet/icon/PlayerIcon.ts&&!file:src/leaflet/icon/GenericIcon.ts&&!file:src/leaflet/tileLayer/DynmapTileLayer.ts&&!file:src/util/areas.ts&&!file:src/util/circles.ts&&!file:src/util/lines.ts&&!file:src/util/markers.ts&&!file[LiveAtlas]:standalone/*&&!file:src/model/LiveAtlasProjection.ts&&!file:src/leaflet/control/LiveAtlasLayerControl.ts&&!file[LiveAtlas]:patches/*&&!file[LiveAtlas]:public/*&&!file[LiveAtlas]:.idea/*&&!file[LiveAtlas]:.idea//*&&!file[LiveAtlas]:patches//*&&!file[LiveAtlas]:public//*&&!file[LiveAtlas]:standalone//*&&!file:FUNDING.yml&&!file:README.md&&!file:tsconfig.json&&!file:.gitignore&&!file:.env&&!file:LICENSE.md&&!file:package-lock.json&&!file:package.json&&!file:vite.config.ts&&!file:index.html&&!file:src/leaflet/control/LoadingControl.ts&&!file:src/scss/style.scss&&!file[LiveAtlas]:src/assets/icons//*&&!file:src/providers/OverviewerMapProvider.ts&&!file:src/providers/DynmapMapProvider.ts&&!file:src/leaflet/projection/OverviewerProjection.ts&&!file:src/leaflet/tileLayer/OverviewerTileLayer.ts&&!file:jest.config.ts&&!file:.npmignore&&!file:plugin.yml&&!file[LiveAtlas]:java/*&&!file[LiveAtlas]:java//*&&!file:src/components/map/control/LoadingControl.vue" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="ui__top-left" class="ui__section section--vertical">
|
<div id="ui__top-left" class="ui__section section--vertical">
|
||||||
<div class="ui__toolbar toolbar--vertical"></div>
|
<div class="ui__toolbar toolbar--vertical">
|
||||||
|
<LoadingControl :leaflet="leaflet" :delay="500"></LoadingControl>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="ui__bottom-left" class="ui__section">
|
<div id="ui__bottom-left" class="ui__section">
|
||||||
@ -52,11 +54,10 @@ import ClockControl from "@/components/map/control/ClockControl.vue";
|
|||||||
import LinkControl from "@/components/map/control/LinkControl.vue";
|
import LinkControl from "@/components/map/control/LinkControl.vue";
|
||||||
import ChatControl from "@/components/map/control/ChatControl.vue";
|
import ChatControl from "@/components/map/control/ChatControl.vue";
|
||||||
import LogoControl from "@/components/map/control/LogoControl.vue";
|
import LogoControl from "@/components/map/control/LogoControl.vue";
|
||||||
import {LoadingControl} from "@/leaflet/control/LoadingControl";
|
|
||||||
import MapContextMenu from "@/components/map/MapContextMenu.vue";
|
import MapContextMenu from "@/components/map/MapContextMenu.vue";
|
||||||
import LoginControl from "@/components/map/control/LoginControl.vue";
|
import LoginControl from "@/components/map/control/LoginControl.vue";
|
||||||
import {onMounted} from "vue";
|
|
||||||
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
|
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
|
||||||
|
import LoadingControl from "@/components/map/control/LoadingControl.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -67,6 +68,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
LoadingControl,
|
||||||
LogoControl,
|
LogoControl,
|
||||||
CoordinatesControl,
|
CoordinatesControl,
|
||||||
LinkControl,
|
LinkControl,
|
||||||
@ -87,13 +89,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
logoControls = computed(() => store.state.components.logoControls);
|
logoControls = computed(() => store.state.components.logoControls);
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
props.leaflet.addControl(new LoadingControl({
|
|
||||||
position: 'topleft',
|
|
||||||
delayIndicator: 500,
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
contextMenuEnabled,
|
contextMenuEnabled,
|
||||||
coordinatesControlEnabled,
|
coordinatesControlEnabled,
|
||||||
|
226
src/components/map/control/LoadingControl.vue
Normal file
226
src/components/map/control/LoadingControl.vue
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
<!--
|
||||||
|
- Copyright 2022 James Lyne
|
||||||
|
-
|
||||||
|
- Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
- you may not use this file except in compliance with the License.
|
||||||
|
- You may obtain a copy of the License at
|
||||||
|
-
|
||||||
|
- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
-
|
||||||
|
- Unless required by applicable law or agreed to in writing, software
|
||||||
|
- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
- See the License for the specific language governing permissions and
|
||||||
|
- limitations under the License.
|
||||||
|
-
|
||||||
|
- Portions of this file are taken from Leaflet.loading:
|
||||||
|
-
|
||||||
|
- Copyright (c) 2013 Eric Brelsford
|
||||||
|
-
|
||||||
|
- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
- of this software and associated documentation files (the "Software"), to deal
|
||||||
|
- in the Software without restriction, including without limitation the rights
|
||||||
|
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
- copies of the Software, and to permit persons to whom the Software is
|
||||||
|
- furnished to do so, subject to the following conditions:
|
||||||
|
-
|
||||||
|
- The above copyright notice and this permission notice shall be included in
|
||||||
|
- all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
- THE SOFTWARE.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="ui__element ui__button loading" :title="loadingTitle" :hidden="!showIndicator">
|
||||||
|
<SvgIcon name="loading"></SvgIcon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {computed, defineComponent, onUnmounted, watch} from "@vue/runtime-core";
|
||||||
|
import SvgIcon from "@/components/SvgIcon.vue";
|
||||||
|
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import {Layer, LayerEvent, LeafletEvent, TileLayer} from "leaflet";
|
||||||
|
import {useStore} from "@/store";
|
||||||
|
import '@/assets/icons/loading.svg';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {SvgIcon},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
leaflet: {
|
||||||
|
type: Object as () => LiveAtlasLeafletMap,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
delay: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup(props) {
|
||||||
|
const store = useStore(),
|
||||||
|
loadingTitle = computed(() => store.state.messages.loadingTitle),
|
||||||
|
dataLoaders = ref<Set<number>>(new Set()),
|
||||||
|
showIndicator = ref<boolean>(false);
|
||||||
|
|
||||||
|
let delayIndicatorTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
const addLayerListeners = () => {
|
||||||
|
// Add listeners for begin and end of load to any layers already
|
||||||
|
// on the map
|
||||||
|
props.leaflet.eachLayer((layer: Layer) => {
|
||||||
|
if(!(layer instanceof TileLayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(layer.isLoading()) {
|
||||||
|
dataLoaders.value.add((layer as any)._leaflet_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.on('loading', handleLoading);
|
||||||
|
layer.on('load', handleLoad);
|
||||||
|
});
|
||||||
|
|
||||||
|
// When a layer is added to the map, add listeners for begin and
|
||||||
|
// end of load
|
||||||
|
props.leaflet.on('layeradd', layerAdd);
|
||||||
|
props.leaflet.on('layerremove', layerRemove);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeLayerListeners = () => {
|
||||||
|
// Remove listeners for begin and end of load from all layers
|
||||||
|
props.leaflet.eachLayer((layer: Layer) => {
|
||||||
|
if(!(layer instanceof TileLayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataLoaders.value.delete((layer as any)._leaflet_id);
|
||||||
|
|
||||||
|
layer.off('loading', handleLoading);
|
||||||
|
layer.off('load', handleLoad);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove layeradd/layerremove listener from map
|
||||||
|
props.leaflet.off('layeradd', layerAdd);
|
||||||
|
props.leaflet.off('layerremove', layerRemove);
|
||||||
|
};
|
||||||
|
|
||||||
|
const layerAdd = (e: LayerEvent) => {
|
||||||
|
if(!(e.layer instanceof TileLayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(e.layer.isLoading()) {
|
||||||
|
handleLoading(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.layer.on('loading', handleLoading);
|
||||||
|
e.layer.on('load', handleLoad);
|
||||||
|
} catch (exception) {
|
||||||
|
console.warn('L.Control.Loading: Tried and failed to add ' +
|
||||||
|
' event handlers to layer', e.layer);
|
||||||
|
console.warn('L.Control.Loading: Full details', exception);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const layerRemove = (e: LayerEvent) => {
|
||||||
|
if(!(e.layer instanceof TileLayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoad(e);
|
||||||
|
|
||||||
|
try {
|
||||||
|
e.layer.off('loading', handleLoading);
|
||||||
|
e.layer.off('load', handleLoad);
|
||||||
|
} catch (exception) {
|
||||||
|
console.warn('L.Control.Loading: Tried and failed to remove ' +
|
||||||
|
'event handlers from layer', e.layer);
|
||||||
|
console.warn('L.Control.Loading: Full details', exception);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoading = (e: LeafletEvent) => dataLoaders.value.add(getEventId(e))
|
||||||
|
const handleLoad = (e: LeafletEvent) => dataLoaders.value.delete(getEventId(e));
|
||||||
|
|
||||||
|
const getEventId = (e: any) => {
|
||||||
|
if (e.id) {
|
||||||
|
return e.id;
|
||||||
|
} else if (e.layer) {
|
||||||
|
return e.layer._leaflet_id;
|
||||||
|
}
|
||||||
|
return e.target._leaflet_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(dataLoaders, (newValue) => {
|
||||||
|
if(props.delay) { // If we are delaying showing the indicator
|
||||||
|
if(newValue.size > 0) {
|
||||||
|
// If we're not already waiting for that delay, set up a timeout.
|
||||||
|
if(!delayIndicatorTimeout) {
|
||||||
|
setTimeout(() => showIndicator.value = true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If removing this loader means we're in no danger of loading,
|
||||||
|
// clear the timeout. This prevents old delays from instantly
|
||||||
|
// triggering the indicator.
|
||||||
|
showIndicator.value = false;
|
||||||
|
clearTimeout(Number(delayIndicatorTimeout));
|
||||||
|
delayIndicatorTimeout = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Otherwise update the indicator immediately
|
||||||
|
showIndicator.value = !!newValue.size;
|
||||||
|
}
|
||||||
|
}, {deep: true});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Add listeners to the map for (custom) dataloading and dataload
|
||||||
|
// events, eg, for AJAX calls that affect the map but will not be
|
||||||
|
// reflected in the above layer events.
|
||||||
|
props.leaflet.on('dataloading', handleLoading);
|
||||||
|
props.leaflet.on('dataload', handleLoad);
|
||||||
|
|
||||||
|
addLayerListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
props.leaflet.off('dataloading', handleLoading);
|
||||||
|
props.leaflet.off('dataload', handleLoad);
|
||||||
|
|
||||||
|
removeLayerListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadingTitle,
|
||||||
|
dataLoaders,
|
||||||
|
showIndicator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.loading {
|
||||||
|
cursor: wait;
|
||||||
|
animation: fade 0.3s linear;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
|
||||||
|
&:hover, &:active, &:focus {
|
||||||
|
background-color: var(--background-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,248 +0,0 @@
|
|||||||
/*
|
|
||||||
Portions of this file are taken from Leaflet.loading:
|
|
||||||
|
|
||||||
Copyright (c) 2013 Eric Brelsford
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
Control,
|
|
||||||
ControlOptions,
|
|
||||||
DomUtil,
|
|
||||||
Layer,
|
|
||||||
LeafletEvent,
|
|
||||||
Map, TileLayer,
|
|
||||||
} from 'leaflet';
|
|
||||||
import '@/assets/icons/loading.svg';
|
|
||||||
import {useStore} from "@/store";
|
|
||||||
|
|
||||||
export interface LoadingControlOptions extends ControlOptions {
|
|
||||||
delayIndicator?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leaflet map control which displays a loading spinner when any tiles are loading
|
|
||||||
*/
|
|
||||||
export class LoadingControl extends Control {
|
|
||||||
declare options: LoadingControlOptions;
|
|
||||||
|
|
||||||
private _dataLoaders: Set<number> = new Set();
|
|
||||||
private readonly _loadingIndicator: HTMLDivElement;
|
|
||||||
private _delayIndicatorTimeout: null | ReturnType<typeof setTimeout> = null;
|
|
||||||
|
|
||||||
constructor(options: LoadingControlOptions) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this._loadingIndicator = DomUtil.create('div',
|
|
||||||
'leaflet-control-button leaflet-control-loading') as HTMLDivElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
onAdd(map: Map) {
|
|
||||||
this._loadingIndicator.title = useStore().state.messages.loadingTitle;
|
|
||||||
this._loadingIndicator.hidden = true;
|
|
||||||
this._loadingIndicator.innerHTML = `
|
|
||||||
<svg class="svg-icon">
|
|
||||||
<use xlink:href="#icon--loading" />
|
|
||||||
</svg>`;
|
|
||||||
|
|
||||||
this._addLayerListeners(map);
|
|
||||||
this._addMapListeners(map);
|
|
||||||
|
|
||||||
return this._loadingIndicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
onRemove(map: Map) {
|
|
||||||
this._removeLayerListeners(map);
|
|
||||||
this._removeMapListeners(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
addLoader(id: number) {
|
|
||||||
this._dataLoaders.add(id);
|
|
||||||
|
|
||||||
if (this.options.delayIndicator && !this._delayIndicatorTimeout) {
|
|
||||||
// If we are delaying showing the indicator and we're not
|
|
||||||
// already waiting for that delay, set up a timeout.
|
|
||||||
this._delayIndicatorTimeout = setTimeout(() => {
|
|
||||||
this.updateIndicator();
|
|
||||||
this._delayIndicatorTimeout = null;
|
|
||||||
}, this.options.delayIndicator);
|
|
||||||
} else {
|
|
||||||
// Otherwise show the indicator immediately
|
|
||||||
this.updateIndicator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeLoader(id: number) {
|
|
||||||
this._dataLoaders.delete(id);
|
|
||||||
this.updateIndicator();
|
|
||||||
|
|
||||||
// If removing this loader means we're in no danger of loading,
|
|
||||||
// clear the timeout. This prevents old delays from instantly
|
|
||||||
// triggering the indicator.
|
|
||||||
if (this.options.delayIndicator && this._delayIndicatorTimeout && !this.isLoading()) {
|
|
||||||
clearTimeout(this._delayIndicatorTimeout);
|
|
||||||
this._delayIndicatorTimeout = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateIndicator() {
|
|
||||||
if (this.isLoading()) {
|
|
||||||
this._showIndicator();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._hideIndicator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoading() {
|
|
||||||
return this._countLoaders() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_countLoaders() {
|
|
||||||
return this._dataLoaders.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
_showIndicator() {
|
|
||||||
this._loadingIndicator.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_hideIndicator() {
|
|
||||||
this._loadingIndicator.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleLoading(e: LeafletEvent) {
|
|
||||||
this.addLoader(this.getEventId(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleBaseLayerChange (e: LeafletEvent) {
|
|
||||||
// Check for a target 'layer' that contains multiple layers, such as
|
|
||||||
// L.LayerGroup. This will happen if you have an L.LayerGroup in an
|
|
||||||
// L.Control.Layers.
|
|
||||||
if (e.layer && e.layer.eachLayer && typeof e.layer.eachLayer === 'function') {
|
|
||||||
e.layer.eachLayer((layer: Layer) => {
|
|
||||||
this._handleBaseLayerChange({ layer: layer } as LeafletEvent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleLoad(e: LeafletEvent) {
|
|
||||||
this.removeLoader(this.getEventId(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
getEventId(e: any) {
|
|
||||||
if (e.id) {
|
|
||||||
return e.id;
|
|
||||||
} else if (e.layer) {
|
|
||||||
return e.layer._leaflet_id;
|
|
||||||
}
|
|
||||||
return e.target._leaflet_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
_layerAdd(e: LeafletEvent) {
|
|
||||||
if(!(e.layer instanceof TileLayer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(e.layer.isLoading()) {
|
|
||||||
this.addLoader((e.layer as any)._leaflet_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
e.layer.on('loading', this._handleLoading, this);
|
|
||||||
e.layer.on('load', this._handleLoad, this);
|
|
||||||
} catch (exception) {
|
|
||||||
console.warn('L.Control.Loading: Tried and failed to add ' +
|
|
||||||
' event handlers to layer', e.layer);
|
|
||||||
console.warn('L.Control.Loading: Full details', exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_layerRemove(e: LeafletEvent) {
|
|
||||||
if(!(e.layer instanceof TileLayer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
e.layer.off('loading', this._handleLoading, this);
|
|
||||||
e.layer.off('load', this._handleLoad, this);
|
|
||||||
} catch (exception) {
|
|
||||||
console.warn('L.Control.Loading: Tried and failed to remove ' +
|
|
||||||
'event handlers from layer', e.layer);
|
|
||||||
console.warn('L.Control.Loading: Full details', exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_addLayerListeners(map: Map) {
|
|
||||||
// Add listeners for begin and end of load to any layers already
|
|
||||||
// on the map
|
|
||||||
map.eachLayer((layer: Layer) => {
|
|
||||||
if(!(layer instanceof TileLayer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(layer.isLoading()) {
|
|
||||||
this.addLoader((layer as any)._leaflet_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
layer.on('loading', this._handleLoading, this);
|
|
||||||
layer.on('load', this._handleLoad, this);
|
|
||||||
});
|
|
||||||
|
|
||||||
// When a layer is added to the map, add listeners for begin and
|
|
||||||
// end of load
|
|
||||||
map.on('layeradd', this._layerAdd, this);
|
|
||||||
map.on('layerremove', this._layerRemove, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_removeLayerListeners(map: Map) {
|
|
||||||
// Remove listeners for begin and end of load from all layers
|
|
||||||
map.eachLayer((layer: Layer) => {
|
|
||||||
if(!(layer instanceof TileLayer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.removeLoader((layer as any)._leaflet_id);
|
|
||||||
|
|
||||||
layer.off('loading', this._handleLoading, this);
|
|
||||||
layer.off('load', this._handleLoad, this);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove layeradd/layerremove listener from map
|
|
||||||
map.off('layeradd', this._layerAdd, this);
|
|
||||||
map.off('layerremove', this._layerRemove, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_addMapListeners(map: Map) {
|
|
||||||
// Add listeners to the map for (custom) dataloading and dataload
|
|
||||||
// events, eg, for AJAX calls that affect the map but will not be
|
|
||||||
// reflected in the above layer events.
|
|
||||||
map.on('baselayerchange', this._handleBaseLayerChange, this);
|
|
||||||
map.on('dataloading', this._handleLoading, this);
|
|
||||||
map.on('dataload', this._handleLoad, this);
|
|
||||||
map.on('layerremove', this._handleLoad, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_removeMapListeners(map: Map) {
|
|
||||||
map.off('baselayerchange', this._handleBaseLayerChange, this);
|
|
||||||
map.off('dataloading', this._handleLoading, this);
|
|
||||||
map.off('dataload', this._handleLoad, this);
|
|
||||||
map.off('layerremove', this._handleLoad, this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -261,17 +261,3 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-control-loading {
|
|
||||||
cursor: wait;
|
|
||||||
animation: fade 0.3s linear;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
|
|
||||||
&:hover, &:active, &:focus {
|
|
||||||
background-color: var(--background-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
&[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user