Migrate CoordinatesControl to vue
This commit is contained in:
parent
c51d2ef554
commit
7471bb794f
@ -14,12 +14,23 @@
|
|||||||
- limitations under the License.
|
- limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="ui__element ui__panel location">
|
||||||
|
<span class="value coordinates" :data-label="componentSettings.label">{{ formattedCoordinates }}</span>
|
||||||
|
<span v-if="componentSettings.showChunk" class="value chunk"
|
||||||
|
:data-label="chunkLabel">{{ formattedChunk }}</span>
|
||||||
|
<span v-if="componentSettings.showRegion" class="value region"
|
||||||
|
:data-label="regionLabel">{{ formattedRegion }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {computed, defineComponent, onMounted, onUnmounted} from "@vue/runtime-core";
|
import {computed, defineComponent, onUnmounted, watch} from "@vue/runtime-core";
|
||||||
import {useStore} from "@/store";
|
import {useStore} from "@/store";
|
||||||
import {CoordinatesControl, CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl";
|
|
||||||
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
|
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
|
||||||
import {watch} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
|
import {Coordinate, CoordinatesControlOptions} from "@/index";
|
||||||
|
import {LeafletMouseEvent} from "leaflet";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -31,26 +42,129 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const store = useStore(),
|
const store = useStore(),
|
||||||
componentSettings = computed(() => store.state.components.coordinatesControl);
|
componentSettings = computed(() => store.state.components.coordinatesControl),
|
||||||
let control = new CoordinatesControl(componentSettings.value as CoordinatesControlOptions);
|
currentMap = computed(() => store.state.currentMap),
|
||||||
|
|
||||||
watch(componentSettings, (newSettings) => {
|
chunkLabel = computed(() => store.state.messages.locationChunk),
|
||||||
props.leaflet.removeControl(control);
|
regionLabel = computed(() => store.state.messages.locationRegion),
|
||||||
|
|
||||||
if(!newSettings) {
|
coordinates = ref<Coordinate|null>(null),
|
||||||
|
|
||||||
|
formattedCoordinates = computed(() => {
|
||||||
|
if(coordinates.value) {
|
||||||
|
const x = Math.round(coordinates.value.x).toString().padStart(5, ' '),
|
||||||
|
y = coordinates.value.y.toString().padStart(3, ' '),
|
||||||
|
z = Math.round(coordinates.value.z).toString().padStart(5, ' ');
|
||||||
|
|
||||||
|
return componentSettings.value!.showY ? `${x}, ${y}, ${z}` : `${x}, ${z}`;
|
||||||
|
} else {
|
||||||
|
return componentSettings.value!.showY ? '-----, ---, -----' : '-----, -----';
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
formattedChunk = computed(() => {
|
||||||
|
if(coordinates.value) {
|
||||||
|
const chunkX = Math.floor(coordinates.value.x / 16).toString().padStart(4, ' '),
|
||||||
|
chunkZ = Math.floor(coordinates.value.z / 16).toString().padStart(4, ' ');
|
||||||
|
|
||||||
|
return `${chunkX}, ${chunkZ}`;
|
||||||
|
} else {
|
||||||
|
return '----, ----'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
formattedRegion = computed(() => {
|
||||||
|
if(coordinates.value) {
|
||||||
|
const regionX = Math.floor(coordinates.value.x / 512).toString().padStart(3, ' '),
|
||||||
|
regionZ = Math.floor(coordinates.value.z / 512).toString().padStart(3, ' ');
|
||||||
|
|
||||||
|
return `r.${regionX}, ${regionZ}.mca`;
|
||||||
|
} else {
|
||||||
|
return '--------------';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onMouseMove = (event: LeafletMouseEvent) => {
|
||||||
|
if (!store.state.currentMap) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
control = new CoordinatesControl(newSettings as CoordinatesControlOptions);
|
coordinates.value = store.state.currentMap.latLngToLocation(event.latlng, store.state.currentWorld!.seaLevel + 1);
|
||||||
props.leaflet.addControl(control);
|
}
|
||||||
}, {deep: true});
|
|
||||||
|
|
||||||
onMounted(() => props.leaflet.addControl(control));
|
const onMouseOut = () => coordinates.value = null;
|
||||||
onUnmounted(() => props.leaflet.removeControl(control));
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
watch(currentMap, newValue => {
|
||||||
return null;
|
if(!newValue) {
|
||||||
|
coordinates.value = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
props.leaflet.on('mousemove', onMouseMove);
|
||||||
|
props.leaflet.on('mouseout', onMouseOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
props.leaflet.off('mousemove', onMouseMove);
|
||||||
|
props.leaflet.off('mouseout', onMouseOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
componentSettings,
|
||||||
|
chunkLabel,
|
||||||
|
regionLabel,
|
||||||
|
formattedCoordinates,
|
||||||
|
formattedChunk,
|
||||||
|
formattedRegion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.location {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.6rem 1.5rem;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
line-height: 1;
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre;
|
||||||
|
font-size: 2rem;
|
||||||
|
|
||||||
|
&[data-label]:before {
|
||||||
|
content: attr(data-label);
|
||||||
|
display: block;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-family: Raleway, sans-serif;;
|
||||||
|
}
|
||||||
|
|
||||||
|
& + .value {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.region {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px), (max-height: 480px) {
|
||||||
|
.value {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 384px) {
|
||||||
|
.chunk {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
8
src/index.d.ts
vendored
8
src/index.d.ts
vendored
@ -26,7 +26,6 @@ import {
|
|||||||
PointTuple,
|
PointTuple,
|
||||||
PolylineOptions
|
PolylineOptions
|
||||||
} from "leaflet";
|
} from "leaflet";
|
||||||
import {CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl";
|
|
||||||
import {LogoControlOptions} from "@/leaflet/control/LogoControl";
|
import {LogoControlOptions} from "@/leaflet/control/LogoControl";
|
||||||
import {globalMessages, serverMessages} from "../messages";
|
import {globalMessages, serverMessages} from "../messages";
|
||||||
import {LiveAtlasMarkerType} from "@/util/markers";
|
import {LiveAtlasMarkerType} from "@/util/markers";
|
||||||
@ -297,6 +296,13 @@ export interface ClockControlOptions extends ControlOptions {
|
|||||||
showWeather: boolean;
|
showWeather: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CoordinatesControlOptions extends ControlOptions {
|
||||||
|
showY: boolean;
|
||||||
|
showRegion: boolean;
|
||||||
|
showChunk: boolean;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface LiveAtlasPartialComponentConfig {
|
interface LiveAtlasPartialComponentConfig {
|
||||||
markers?: {
|
markers?: {
|
||||||
showLabels: boolean;
|
showLabels: boolean;
|
||||||
|
@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 James Lyne
|
|
||||||
*
|
|
||||||
* Some portions of this file were taken from https://github.com/webbukkit/dynmap.
|
|
||||||
* These portions are Copyright 2020 Dynmap Contributors.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {ControlOptions, LeafletMouseEvent, Control, Map, DomUtil, Util} from 'leaflet';
|
|
||||||
import {useStore} from "@/store";
|
|
||||||
import {Coordinate} from "@/index";
|
|
||||||
|
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
export interface CoordinatesControlOptions extends ControlOptions {
|
|
||||||
showY: boolean;
|
|
||||||
showRegion: boolean;
|
|
||||||
showChunk: boolean;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leaflet map control which displays in-game block coordinates when hovering over or tapping the map
|
|
||||||
*/
|
|
||||||
export class CoordinatesControl extends Control {
|
|
||||||
declare options: CoordinatesControlOptions;
|
|
||||||
declare _map ?: Map;
|
|
||||||
|
|
||||||
private _location?: Coordinate;
|
|
||||||
private _locationChanged: boolean = false;
|
|
||||||
private readonly _coordsContainer: HTMLSpanElement;
|
|
||||||
private readonly _regionContainer: HTMLSpanElement;
|
|
||||||
private readonly _chunkContainer: HTMLSpanElement;
|
|
||||||
|
|
||||||
constructor(options: CoordinatesControlOptions) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this._coordsContainer = DomUtil.create('span', 'value coordinates');
|
|
||||||
this._chunkContainer = DomUtil.create('span', 'value chunk');
|
|
||||||
this._regionContainer = DomUtil.create('span', 'value region');
|
|
||||||
|
|
||||||
options.position = 'bottomleft';
|
|
||||||
Util.setOptions(this, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
onAdd(map: Map) {
|
|
||||||
const container = DomUtil.create('div', 'leaflet-control-coordinates');
|
|
||||||
|
|
||||||
this._coordsContainer.textContent = this.options.showY ? '-----, ---, -----' : '-----, -----';
|
|
||||||
this._coordsContainer.dataset.label = this.options.label;
|
|
||||||
container.appendChild(this._coordsContainer);
|
|
||||||
|
|
||||||
if (this.options.showRegion) {
|
|
||||||
this._regionContainer.textContent = '--------------';
|
|
||||||
this._regionContainer.dataset.label = store.state.messages.locationRegion;
|
|
||||||
container.appendChild(this._regionContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.showChunk) {
|
|
||||||
this._chunkContainer.textContent = '----, ----';
|
|
||||||
this._chunkContainer.dataset.label = store.state.messages.locationChunk;
|
|
||||||
container.appendChild(this._chunkContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
map.on('mousemove', this._onMouseMove, this);
|
|
||||||
map.on('mouseout', this._onMouseOut, this);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
if (!this._map) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._map.off('mousemove', this._onMouseMove, this);
|
|
||||||
this._map.off('mouseout', this._onMouseOut, this);
|
|
||||||
super.remove();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMouseMove(event: LeafletMouseEvent) {
|
|
||||||
if (!this._map || !store.state.currentMap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._location = store.state.currentMap.latLngToLocation(event.latlng, store.state.currentWorld!.seaLevel + 1);
|
|
||||||
|
|
||||||
if(!this._locationChanged) {
|
|
||||||
this._locationChanged = true;
|
|
||||||
requestAnimationFrame(() => this._update());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMouseOut() {
|
|
||||||
if (!this._map) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._location = undefined;
|
|
||||||
|
|
||||||
if(!this._locationChanged) {
|
|
||||||
this._locationChanged = true;
|
|
||||||
requestAnimationFrame(() => this._update());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_update() {
|
|
||||||
if (!this._map || !store.state.currentWorld || !this._locationChanged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._locationChanged = false;
|
|
||||||
|
|
||||||
if(!this._location) {
|
|
||||||
if (this.options.showY) {
|
|
||||||
this._coordsContainer.textContent = '-----, ---, -----';
|
|
||||||
} else {
|
|
||||||
this._coordsContainer.textContent = '-----, -----';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.showRegion) {
|
|
||||||
this._regionContainer.textContent = '--------------';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.showChunk) {
|
|
||||||
this._chunkContainer.textContent = '----, ----';
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const x = Math.round(this._location.x).toString().padStart(5, ' '),
|
|
||||||
y = this._location.y.toString().padStart(3, ' '),
|
|
||||||
z = Math.round(this._location.z).toString().padStart(5, ' '),
|
|
||||||
regionX = Math.floor(this._location.x / 512).toString().padStart(3, ' '),
|
|
||||||
regionZ = Math.floor(this._location.z / 512).toString().padStart(3, ' '),
|
|
||||||
chunkX = Math.floor(this._location.x / 16).toString().padStart(4, ' '),
|
|
||||||
chunkZ = Math.floor(this._location.z / 16).toString().padStart(4, ' ');
|
|
||||||
|
|
||||||
if (this.options.showY) {
|
|
||||||
this._coordsContainer.textContent = `${x}, ${y}, ${z}`;
|
|
||||||
} else {
|
|
||||||
this._coordsContainer.textContent = `${x}, ${z}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.showRegion) {
|
|
||||||
this._regionContainer.textContent = `r.${regionX}, ${regionZ}.mca`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.showChunk) {
|
|
||||||
this._chunkContainer.textContent = `${chunkX}, ${chunkZ}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -99,50 +99,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-control-coordinates {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
|
|
||||||
.value {
|
|
||||||
line-height: 1;
|
|
||||||
font-family: monospace;
|
|
||||||
white-space: pre;
|
|
||||||
font-size: 2rem;
|
|
||||||
|
|
||||||
&[data-label]:before {
|
|
||||||
content: attr(data-label);
|
|
||||||
display: block;
|
|
||||||
line-height: 1;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-family: Raleway, sans-serif;;
|
|
||||||
}
|
|
||||||
|
|
||||||
& + .value {
|
|
||||||
margin-left: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.region {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 480px), (max-height: 480px) {
|
|
||||||
.value {
|
|
||||||
font-size: 1.6rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 384px) {
|
|
||||||
.chunk {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-control-layers {
|
.leaflet-control-layers {
|
||||||
width: auto;
|
width: auto;
|
||||||
border: none;
|
border: none;
|
||||||
|
Loading…
Reference in New Issue
Block a user