Merker set changes
- Use separate panes for each marker set - Set pane z-index based on marker set priority - Optimize zoom visibility checks
This commit is contained in:
parent
f7d1ef4cfc
commit
0eea500098
@ -52,10 +52,16 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
|
||||
setup() {
|
||||
setup(props) {
|
||||
const store = useStore(),
|
||||
markerSettings = computed(() => store.state.components.markers),
|
||||
layerGroup = new DynmapLayerGroup();
|
||||
layerGroup = new DynmapLayerGroup({
|
||||
id: props.markerSet.id,
|
||||
minZoom: props.markerSet.minZoom,
|
||||
maxZoom: props.markerSet.maxZoom,
|
||||
showLabels: props.markerSet.showLabels || store.state.components.markers.showLabels,
|
||||
priority: props.markerSet.priority,
|
||||
});
|
||||
|
||||
return {
|
||||
markerSettings,
|
||||
|
@ -14,9 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Layer, Map as LeafletMap, LayerGroup, LayerOptions, Util} from "leaflet";
|
||||
import {Layer, Map as LeafletMap, LayerGroup, LayerOptions, Util, Marker, Path} from "leaflet";
|
||||
|
||||
export interface DynmapLayerGroupOptions extends LayerOptions {
|
||||
id: string; //Added to the name of layer group panes
|
||||
showLabels: boolean;
|
||||
priority: number; //Added to the z-index of layer group panes
|
||||
|
||||
//Zoom limits for the whole group, can be overridden by layers
|
||||
minZoom?: number;
|
||||
maxZoom?: number;
|
||||
}
|
||||
@ -24,33 +29,44 @@ export interface DynmapLayerGroupOptions extends LayerOptions {
|
||||
export default class DynmapLayerGroup extends LayerGroup {
|
||||
// @ts-ignore
|
||||
options: DynmapLayerGroupOptions;
|
||||
_layerVisibility: Map<Layer, boolean>;
|
||||
_zoomLimitedLayers: Set<Layer>; //Layers which are zoom limited and should be checked on zoom
|
||||
_layers: any;
|
||||
_markerPane?: HTMLElement;
|
||||
_vectorPane?: HTMLElement;
|
||||
|
||||
constructor(layers?: Layer[], options?: DynmapLayerGroupOptions) {
|
||||
super(layers, options);
|
||||
_zoomEndCallback = () => this._updateLayerVisibility();
|
||||
|
||||
constructor(options: DynmapLayerGroupOptions) {
|
||||
super([], options);
|
||||
Util.setOptions(this, options);
|
||||
|
||||
this._layerVisibility = new Map();
|
||||
this._zoomLimitedLayers = new Set();
|
||||
}
|
||||
|
||||
onAdd(map: LeafletMap) {
|
||||
map.on('zoomend', this._handleZoomChange, this);
|
||||
this._handleZoomChange();
|
||||
map.on('zoomend', this._zoomEndCallback, this);
|
||||
|
||||
this._map = map;
|
||||
this._markerPane = map.createPane(`${this.options.id}-markers`);
|
||||
this._vectorPane = map.createPane(`${this.options.id}-vectors`);
|
||||
|
||||
this._markerPane.style.zIndex = (401 + this.options.priority).toString();
|
||||
this._vectorPane.style.zIndex = (400 + this.options.priority).toString();
|
||||
|
||||
this._updateLayerVisibility(true);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
onRemove(map: LeafletMap) {
|
||||
super.onRemove(map);
|
||||
this._layerVisibility.clear();
|
||||
map.off('zoomend', this._handleZoomChange, this);
|
||||
map.off('zoomend', this._zoomEndCallback, this);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
clearLayers(): this {
|
||||
this._layerVisibility.clear();
|
||||
this._zoomLimitedLayers.clear();
|
||||
return super.clearLayers();
|
||||
}
|
||||
|
||||
@ -59,53 +75,81 @@ export default class DynmapLayerGroup extends LayerGroup {
|
||||
|
||||
this._layers[id] = layer;
|
||||
|
||||
if (layer instanceof Marker) {
|
||||
layer.options.pane = `${this.options.id}-markers`;
|
||||
} else if (layer instanceof Path) {
|
||||
layer.options.pane = `${this.options.id}-vectors`;
|
||||
}
|
||||
|
||||
if(this._map) {
|
||||
const visible = this._isLayerVisible(layer, this._map.getZoom());
|
||||
this._layerVisibility.set(layer, visible);
|
||||
const zoomLimited = this._isLayerZoomLimited(layer);
|
||||
|
||||
if(visible) {
|
||||
if (zoomLimited) {
|
||||
this._zoomLimitedLayers.add(layer);
|
||||
}
|
||||
|
||||
if (this._map) {
|
||||
//If layer is zoom limited, only add to map if it should be visible
|
||||
if (zoomLimited) {
|
||||
if (this._isLayerVisible(layer, this._map.getZoom())) {
|
||||
this._map.addLayer(layer);
|
||||
}
|
||||
} else {
|
||||
this._map.addLayer(layer);
|
||||
}
|
||||
} else {
|
||||
this._layerVisibility.set(layer, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
removeLayer(layer: Layer): this {
|
||||
this._layerVisibility.delete(layer);
|
||||
this._zoomLimitedLayers.delete(layer);
|
||||
return super.addLayer(layer);
|
||||
}
|
||||
|
||||
_handleZoomChange() {
|
||||
_updateLayerVisibility(onAdd?: boolean) {
|
||||
if(!this._map) {
|
||||
return;
|
||||
}
|
||||
|
||||
const zoom = this._map.getZoom();
|
||||
|
||||
//FIXME: Keep track of layers that actually have min/max zoom, to avoid pointless checking of every layer?
|
||||
this.eachLayer((layer) => {
|
||||
const newVisibility = this._isLayerVisible(layer, zoom),
|
||||
currentVisibility = this._layerVisibility.get(layer);
|
||||
//The whole group is zoom limited
|
||||
if(this._isZoomLimited()) {
|
||||
const visible = zoom >= (this.options.minZoom || -Infinity) && zoom <= (this.options.maxZoom || Infinity);
|
||||
|
||||
if(newVisibility) {
|
||||
if(!currentVisibility) {
|
||||
this._map.addLayer(layer);
|
||||
}
|
||||
} else if(currentVisibility) {
|
||||
this._map.removeLayer(layer);
|
||||
this.eachLayer((layer) => {
|
||||
//Per marker zoom limits take precedence, if present
|
||||
if(this._zoomLimitedLayers.has(layer)) {
|
||||
this._isLayerVisible(layer, zoom) ? this._map.addLayer(layer) : this._map.removeLayer(layer);
|
||||
} else { //Otherwise apply group zoom limit
|
||||
visible ? this._map.addLayer(layer) : this._map.removeLayer(layer);
|
||||
}
|
||||
}, this);
|
||||
//Group isn't zoom limited, but some individual markers are
|
||||
} else if(this._zoomLimitedLayers.size) {
|
||||
this._zoomLimitedLayers.forEach((layer) => {
|
||||
this._isLayerVisible(layer, zoom) ? this._map.addLayer(layer) : this._map.removeLayer(layer);
|
||||
});
|
||||
//Nothing is zoom limited, but we've just been added to the map
|
||||
} else if(onAdd) {
|
||||
this.eachLayer(this._map.addLayer, this._map);
|
||||
}
|
||||
}
|
||||
|
||||
this._layerVisibility.set(layer, newVisibility);
|
||||
}, this);
|
||||
//Returns if this layer group has zoom limits defined
|
||||
_isZoomLimited() {
|
||||
return this.options.maxZoom !== undefined || this.options.minZoom !== undefined;
|
||||
}
|
||||
|
||||
//Returns if the given layer has its own zoom limits defined
|
||||
_isLayerZoomLimited(layer: Layer) {
|
||||
return ((layer as any).options && (layer as any).options.minZoom !== undefined)
|
||||
&& ((layer as any).options && (layer as any).options.maxZoom !== undefined);
|
||||
}
|
||||
|
||||
_isLayerVisible(layer: Layer, currentZoom: number) {
|
||||
let minZoom = this.options.minZoom || -Infinity,
|
||||
maxZoom = this.options.maxZoom || Infinity;
|
||||
let minZoom = -Infinity,
|
||||
maxZoom = Infinity;
|
||||
|
||||
if((layer as any).options && (layer as any).options.minZoom !== undefined) {
|
||||
minZoom = (layer as any).options.minZoom;
|
||||
|
Loading…
Reference in New Issue
Block a user