Start layer control implementation

This commit is contained in:
James Lyne 2020-12-11 21:38:50 +00:00
parent 52bb6f5778
commit ca82f56185
13 changed files with 106 additions and 134 deletions

View File

@ -5,7 +5,7 @@ import {
DynmapComponentConfig, DynmapComponentConfig,
DynmapConfigurationResponse, DynmapConfigurationResponse,
DynmapLine, DynmapLine,
DynmapMap, DynmapWorldMap,
DynmapMarker, DynmapMarker,
DynmapMarkerSet, DynmapMarkerSet,
DynmapMarkerSetUpdates, DynmapMarkerSetUpdates,
@ -60,7 +60,7 @@ function buildWorlds(response: AxiosResponse): Array<DynmapWorld> {
worlds: Array<DynmapWorld> = []; worlds: Array<DynmapWorld> = [];
(data.worlds || []).forEach((world: any) => { (data.worlds || []).forEach((world: any) => {
const maps: Map<string, DynmapMap> = new Map(); const maps: Map<string, DynmapWorldMap> = new Map();
(world.maps || []).forEach((map: any) => { (world.maps || []).forEach((map: any) => {
maps.set(map.name, { maps.set(map.name, {

View File

@ -14,7 +14,6 @@
<script lang="ts"> <script lang="ts">
import {defineComponent, computed} from "@vue/runtime-core"; import {defineComponent, computed} from "@vue/runtime-core";
import L from 'leaflet'; import L from 'leaflet';
import '@/leaflet/map';
import {useStore} from '@/store'; import {useStore} from '@/store';
import MapLayer from "@/components/map/layer/MapLayer.vue"; import MapLayer from "@/components/map/layer/MapLayer.vue";
import PlayersLayer from "@/components/map/layer/PlayersLayer.vue"; import PlayersLayer from "@/components/map/layer/PlayersLayer.vue";
@ -26,6 +25,7 @@ import LogoControl from "@/components/map/control/LogoControl.vue";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {DynmapPlayer} from "@/dynmap"; import {DynmapPlayer} from "@/dynmap";
import {ActionTypes} from "@/store/action-types"; import {ActionTypes} from "@/store/action-types";
import DynmapMap from "@/leaflet/DynmapMap";
export default defineComponent({ export default defineComponent({
components: { components: {
@ -92,7 +92,6 @@ export default defineComponent({
}, },
configuration: { configuration: {
handler(newValue) { handler(newValue) {
console.log(newValue.defaultZoom);
if(this.leaflet) { if(this.leaflet) {
this.leaflet.setZoom(newValue.defaultZoom, { this.leaflet.setZoom(newValue.defaultZoom, {
animate: false, animate: false,
@ -105,12 +104,13 @@ export default defineComponent({
}, },
mounted() { mounted() {
this.leaflet = new L.Map(this.$el, Object.freeze({ this.leaflet = new DynmapMap(this.$el, Object.freeze({
zoom: this.configuration.defaultZoom, zoom: this.configuration.defaultZoom,
center: new L.LatLng(0, 0), center: new L.LatLng(0, 0),
fadeAnimation: false, fadeAnimation: false,
zoomAnimation: true, zoomAnimation: true,
zoomControl: true, zoomControl: true,
layerControl: true,
preferCanvas: true, preferCanvas: true,
attributionControl: false, attributionControl: false,
crs: L.CRS.Simple, crs: L.CRS.Simple,
@ -118,10 +118,6 @@ export default defineComponent({
// markerZoomAnimation: false, // markerZoomAnimation: false,
})); }));
this.leaflet.addControl(new L.Control.Layers({}, {},{
position: 'topleft',
}));
this.leaflet.on('moveend', () => { this.leaflet.on('moveend', () => {
const location = this.currentProjection.latLngToLocation(this.leaflet!.getCenter(), 64), const location = this.currentProjection.latLngToLocation(this.leaflet!.getCenter(), 64),
locationString = `${Math.round(location.x)},${Math.round(location.y)},${Math.round(location.z)}`, locationString = `${Math.round(location.x)},${Math.round(location.y)},${Math.round(location.z)}`,

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import {defineComponent, onMounted, onUnmounted, computed, watch} from "@vue/runtime-core"; import {defineComponent, onMounted, onUnmounted, computed, watch} from "@vue/runtime-core";
import {DynmapMap} from "@/dynmap"; import {DynmapWorldMap} from "@/dynmap";
import {Map} from 'leaflet'; import {Map} from 'leaflet';
import {useStore} from "@/store"; import {useStore} from "@/store";
import {HDMapType} from "@/leaflet/mapType/HDMapType"; import {HDMapType} from "@/leaflet/mapType/HDMapType";
@ -14,7 +14,7 @@ export default defineComponent({
required: true required: true
}, },
map: { map: {
type: Object as () => DynmapMap, type: Object as () => DynmapWorldMap,
required: true required: true
}, },
leaflet: { leaflet: {

View File

@ -14,6 +14,7 @@ import GenericMarker from "@/components/map/marker/GenericMarker.vue";
import Areas from "@/components/map/vector/Areas.vue"; import Areas from "@/components/map/vector/Areas.vue";
import Circles from "@/components/map/vector/Circles.vue"; import Circles from "@/components/map/vector/Circles.vue";
import Lines from "@/components/map/vector/Lines.vue"; import Lines from "@/components/map/vector/Lines.vue";
import DynmapMap from "@/leaflet/DynmapMap";
export default defineComponent({ export default defineComponent({
components: { components: {
@ -25,7 +26,7 @@ export default defineComponent({
props: { props: {
leaflet: { leaflet: {
type: Object as () => L.Map, type: Object as () => DynmapMap,
required: true, required: true,
}, },
@ -51,13 +52,13 @@ export default defineComponent({
if(!this.markerSet.hidden) { if(!this.markerSet.hidden) {
// console.log('Adding markerSetLayer'); // console.log('Adding markerSetLayer');
this.leaflet.addLayer(this.layerGroup); this.leaflet.getLayerManager().addLayer(this.layerGroup, true, this.markerSet.label, 1);
} }
}, },
unmounted() { unmounted() {
// console.log('Unmounted markerSetLayer'); // console.log('Unmounted markerSetLayer');
this.leaflet.removeLayer(this.layerGroup); this.leaflet.getLayerManager().removeLayer(this.layerGroup);
}, },
render() { render() {

View File

@ -7,6 +7,7 @@ import PlayerMarker from "@/components/map/marker/PlayerMarker.vue";
import {defineComponent, computed} from "@vue/runtime-core"; import {defineComponent, computed} from "@vue/runtime-core";
import {useStore} from "@/store"; import {useStore} from "@/store";
import L from 'leaflet'; import L from 'leaflet';
import DynmapMap from "@/leaflet/DynmapMap";
export default defineComponent({ export default defineComponent({
components: { components: {
@ -15,7 +16,7 @@ export default defineComponent({
props: { props: {
leaflet: { leaflet: {
type: Object as () => L.Map, type: Object as () => DynmapMap,
required: true, required: true,
} }
}, },
@ -37,7 +38,7 @@ export default defineComponent({
// console.log('Mounted playersLayer'); // console.log('Mounted playersLayer');
if(!this.componentSettings!.hideByDefault) { if(!this.componentSettings!.hideByDefault) {
// console.log('Adding playersLayer'); // console.log('Adding playersLayer');
this.leaflet.addLayer(this.layerGroup); this.leaflet.getLayerManager().addLayer(this.layerGroup, true, useStore().state.messages.players, 1);
} }
}, },

View File

@ -12,7 +12,7 @@
<script lang="ts"> <script lang="ts">
import {useStore} from "@/store"; import {useStore} from "@/store";
import {DynmapMap, DynmapWorld} from "@/dynmap"; import {DynmapWorldMap, DynmapWorld} from "@/dynmap";
import {defineComponent} from 'vue'; import {defineComponent} from 'vue';
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
@ -26,13 +26,13 @@ export default defineComponent({
}, },
computed: { computed: {
currentMap(): DynmapMap | undefined { currentMap(): DynmapWorldMap | undefined {
return useStore().state.currentMap; return useStore().state.currentMap;
} }
}, },
methods: { methods: {
getMapIcon(map: DynmapMap): string { getMapIcon(map: DynmapWorldMap): string {
let worldType: string, let worldType: string,
mapType: string; mapType: string;

4
src/dynmap.d.ts vendored
View File

@ -85,10 +85,10 @@ interface DynmapWorld {
title: string; title: string;
height: number; height: number;
center: Coordinate; center: Coordinate;
maps: Map<String, DynmapMap>; maps: Map<String, DynmapWorldMap>;
} }
interface DynmapMap { interface DynmapWorldMap {
world: DynmapWorld; world: DynmapWorld;
background: string; background: string;
backgroundDay: string; backgroundDay: string;

49
src/leaflet/DynmapMap.ts Normal file
View File

@ -0,0 +1,49 @@
import L, {MapOptions} from 'leaflet';
import LayerManager from "@/leaflet/layer/LayerManager";
interface DynmapMapOptions extends MapOptions {
layerControl: boolean;
}
export default class DynmapMap extends L.Map {
private readonly _layerManager: LayerManager;
private _controlCorners: any;
private _controlContainer?: HTMLElement;
private _container?: HTMLElement;
constructor(element: string | HTMLElement, options?: DynmapMapOptions) {
super(element, options);
this._layerManager = Object.seal(new LayerManager(this, options?.layerControl));
}
getLayerManager(): LayerManager {
return this._layerManager;
}
_initControlPos() {
const corners: any = this._controlCorners = {},
l = 'leaflet-',
container = this._controlContainer =
L.DomUtil.create('div', l + 'control-container', this._container);
function createCorner(vSide: string, hSide: string) {
const className = l + vSide + ' ' + l + hSide;
corners[`${vSide}${hSide}`] = L.DomUtil.create('div', className, container);
}
createCorner('top', 'left');
createCorner('top', 'bar');
createCorner('top', 'right');
createCorner('top', 'center');
createCorner('bottom', 'center');
createCorner('bottom', 'bar');
createCorner('bottom', 'left');
createCorner('bottom', 'right');
}
getUrl() {
}
}

View File

@ -1,78 +0,0 @@
import L, {ControlOptions, ControlPosition, LeafletMouseEvent} from 'leaflet';
import {useStore} from "@/store";
const store = useStore();
export interface CoordinatesControlOptions extends ControlOptions {
showY: boolean;
showRegion: boolean;
showChunk: boolean;
label: string;
}
export class LayerControl extends L.Control.Layers {
constructor() {
super();
}
// Function override to include pos
addOverlay(layer: L.Layer, name: string, pos: number) {
this._addLayer(layer, name, true, pos);
this._update();
return this;
}
// Function override to order layers by pos
_addLayer(layer: L.Layer, name: string, overlay, pos: number) {
var id = L.stamp(layer);
this._layers[pos] = {
layer: layer,
name: name,
overlay: overlay,
id: id
};
if (this.options.autoZIndex && layer.setZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
}
// Function override to convert the position-based ordering into the id-based ordering
_onInputClick() {
var i, input, obj,
inputs = this._form.getElementsByTagName('input'),
inputsLen = inputs.length,
baseLayer;
this._handlingClick = true;
// Convert ID to pos
var id2pos = {};
for (i in this._layers) {
id2pos[this._layers[i].id] = i;
}
for (i = 0; i < inputsLen; i++) {
input = inputs[i];
obj = this._layers[id2pos[input.layerId]];
if (input.checked && !this._map.hasLayer(obj.layer)) {
this._map.addLayer(obj.layer);
if (!obj.overlay) {
baseLayer = obj.layer;
}
} else if (!input.checked && this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer);
}
}
if (baseLayer) {
this._map.setZoom(this._map.getZoom());
this._map.fire('baselayerchange', {layer: baseLayer});
}
this._handlingClick = false;
}
}

View File

@ -0,0 +1,32 @@
import L from 'leaflet';
export default class LayerManager {
private showControl: boolean = false;
private readonly layerControl: L.Control.Layers;
private readonly map: L.Map;
constructor(map: L.Map, showControl?: boolean) {
this.showControl = showControl || this.showControl;
this.map = map;
this.layerControl = new L.Control.Layers({}, {},{
position: 'topleft',
});
if(this.showControl) {
this.map.addControl(this.layerControl);
}
}
addLayer(layer: L.Layer, showInControl: boolean, name: string, position: number) {
this.map.addLayer(layer);
if(showInControl) {
this.layerControl.addOverlay(layer, name);
}
}
removeLayer(layer: L.Layer) {
this.map.removeLayer(layer);
this.layerControl.removeLayer(layer);
}
}

View File

@ -1,29 +0,0 @@
import L from 'leaflet';
L.Map.include({
_initControlPos: function () {
const corners: any = this._controlCorners = {},
l = 'leaflet-',
container = this._controlContainer =
L.DomUtil.create('div', l + 'control-container', this._container);
function createCorner(vSide: string, hSide: string) {
const className = l + vSide + ' ' + l + hSide;
corners[`${vSide}${hSide}`] = L.DomUtil.create('div', className, container);
}
createCorner('top', 'left');
createCorner('top', 'bar');
createCorner('top', 'right');
createCorner('top', 'center');
createCorner('bottom', 'center');
createCorner('bottom', 'bar');
createCorner('bottom', 'left');
createCorner('bottom', 'right');
},
getUrl() {
}
});

View File

@ -1,16 +1,16 @@
import L, {Coords, DoneCallback, TileLayerOptions} from 'leaflet'; import L, {Coords, DoneCallback, TileLayerOptions} from 'leaflet';
import {DynmapProjection} from "@/leaflet/projection/DynmapProjection"; import {DynmapProjection} from "@/leaflet/projection/DynmapProjection";
import {Coordinate, DynmapMap} from "@/dynmap"; import {Coordinate, DynmapWorldMap} from "@/dynmap";
export interface DynmapTileLayerOptions extends TileLayerOptions { export interface DynmapTileLayerOptions extends TileLayerOptions {
mapSettings: DynmapMap; mapSettings: DynmapWorldMap;
errorTileUrl: string; errorTileUrl: string;
} }
export interface DynmapTileLayer extends L.TileLayer { export interface DynmapTileLayer extends L.TileLayer {
options: DynmapTileLayerOptions; options: DynmapTileLayerOptions;
_projection: DynmapProjection; _projection: DynmapProjection;
_mapSettings: DynmapMap; _mapSettings: DynmapWorldMap;
_cachedTileUrls: Map<string, string>; _cachedTileUrls: Map<string, string>;
_namedTiles: Map<string, DynmapTileElement>; _namedTiles: Map<string, DynmapTileElement>;
_tileTemplate: DynmapTileElement; _tileTemplate: DynmapTileElement;

View File

@ -1,6 +1,6 @@
import { import {
DynmapComponentConfig, DynmapComponentConfig,
DynmapMap, DynmapMarkerSet, DynmapMarkerSetUpdates, DynmapWorldMap, DynmapMarkerSet, DynmapMarkerSetUpdates,
DynmapMessageConfig, DynmapMessageConfig,
DynmapPlayer, DynmapPlayer,
DynmapServerConfig, DynmapTileUpdate, DynmapServerConfig, DynmapTileUpdate,
@ -14,7 +14,7 @@ export type State = {
components: DynmapComponentConfig; components: DynmapComponentConfig;
worlds: Map<string, DynmapWorld>; worlds: Map<string, DynmapWorld>;
maps: Map<string, DynmapMap>; maps: Map<string, DynmapWorldMap>;
players: Map<string, DynmapPlayer>; players: Map<string, DynmapPlayer>;
markerSets: Map<string, DynmapMarkerSet>; markerSets: Map<string, DynmapMarkerSet>;
@ -25,7 +25,7 @@ export type State = {
currentWorldState: DynmapWorldState; currentWorldState: DynmapWorldState;
currentWorld?: DynmapWorld; currentWorld?: DynmapWorld;
currentMap?: DynmapMap; currentMap?: DynmapWorldMap;
currentProjection: DynmapProjection; currentProjection: DynmapProjection;
updateRequestId: number; updateRequestId: number;