Implement display of lines and circles
This commit is contained in:
parent
34b0e5f259
commit
a809b68bb2
@ -231,7 +231,7 @@ function buildLines(data: any): Map<string, DynmapLine> {
|
|||||||
|
|
||||||
lines.set(key, {
|
lines.set(key, {
|
||||||
x: line.x || [0, 0],
|
x: line.x || [0, 0],
|
||||||
y: [line.ybottom || 0, line.ytop || 0],
|
y: line.y || [0, 0],
|
||||||
z: line.z || [0, 0],
|
z: line.z || [0, 0],
|
||||||
style: {
|
style: {
|
||||||
color: line.color || '#ff0000',
|
color: line.color || '#ff0000',
|
||||||
@ -322,7 +322,8 @@ export default {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
for(let i = 0; i < 408; i++) {
|
//Extra fake players for testing
|
||||||
|
for(let i = 0; i < 150; i++) {
|
||||||
players.add({
|
players.add({
|
||||||
account: "VIDEO GAMES " + i,
|
account: "VIDEO GAMES " + i,
|
||||||
health: Math.round(Math.random() * 10),
|
health: Math.round(Math.random() * 10),
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<GenericMarker v-for="[id, marker] in markerSet.markers" :options="marker" :key="id" :layer-group="layerGroup"></GenericMarker>
|
<GenericMarker v-for="[id, marker] in markerSet.markers" :options="marker" :key="id" :layer-group="layerGroup"></GenericMarker>
|
||||||
<Areas :areas="markerSet.areas" :layer-group="layerGroup"></Areas>
|
<Areas :areas="markerSet.areas" :layer-group="layerGroup"></Areas>
|
||||||
|
<Circles :circles="markerSet.circles" :layer-group="layerGroup"></Circles>
|
||||||
|
<Lines :lines="markerSet.lines" :layer-group="layerGroup"></Lines>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -10,11 +12,15 @@ import L from 'leaflet';
|
|||||||
import {DynmapMarkerSet} from "@/dynmap";
|
import {DynmapMarkerSet} from "@/dynmap";
|
||||||
import GenericMarker from "@/components/map/marker/GenericMarker.vue";
|
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 Lines from "@/components/map/vector/Lines.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
GenericMarker,
|
GenericMarker,
|
||||||
Areas
|
Areas,
|
||||||
|
Circles,
|
||||||
|
Lines,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
140
src/components/map/vector/Circles.vue
Normal file
140
src/components/map/vector/Circles.vue
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {defineComponent, computed} from "@vue/runtime-core";
|
||||||
|
import L, {LatLngExpression} from 'leaflet';
|
||||||
|
import {useStore} from "@/store";
|
||||||
|
import {DynmapCircle} from "@/dynmap";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
circles: {
|
||||||
|
type: Object as () => Map<string, DynmapCircle>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
layerGroup: {
|
||||||
|
type: Object as () => L.LayerGroup,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const store = useStore(),
|
||||||
|
currentProjection = computed(() => store.state.currentProjection),
|
||||||
|
layers = Object.freeze(new Map()) as Map<string, L.Path>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
layers,
|
||||||
|
currentProjection,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
//FIXME: Prevent unnecessary repositioning when changing worlds
|
||||||
|
currentProjection() {
|
||||||
|
const projection = useStore().state.currentProjection,
|
||||||
|
latLng = (x: number, y: number, z: number) => {
|
||||||
|
return projection.locationToLatLng({x, y, z});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for (const [id, circle] of this.circles) {
|
||||||
|
this.updateCircle(id, circle, latLng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.createCircles();
|
||||||
|
},
|
||||||
|
|
||||||
|
unmounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
createCircles() {
|
||||||
|
const projection = useStore().state.currentProjection,
|
||||||
|
latLng = (x: number, y: number, z: number) => {
|
||||||
|
return projection.locationToLatLng({x, y, z});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.circles.forEach((circle: DynmapCircle, id: string) => {
|
||||||
|
this.createCircle(id, circle, latLng);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
createCircle(id: string, options: DynmapCircle, latLng: Function) {
|
||||||
|
const outline = !options.style.fillOpacity || (options.style.fillOpacity <= 0),
|
||||||
|
points = this.getPoints(options, latLng, outline);
|
||||||
|
let circle;
|
||||||
|
|
||||||
|
if(outline) {
|
||||||
|
circle = new L.Polyline(points, options.style);
|
||||||
|
} else {
|
||||||
|
circle = new L.Polygon(points, options.style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.label) {
|
||||||
|
circle.bindPopup(() => {
|
||||||
|
const popup = document.createElement('span');
|
||||||
|
|
||||||
|
if (options.popupContent) {
|
||||||
|
popup.classList.add('CirclePopup');
|
||||||
|
popup.insertAdjacentHTML('afterbegin', options.popupContent);
|
||||||
|
} else if (options.isHTML) {
|
||||||
|
popup.classList.add('CirclePopup');
|
||||||
|
popup.insertAdjacentHTML('afterbegin', options.label);
|
||||||
|
} else {
|
||||||
|
popup.textContent = options.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layers.set(id, circle);
|
||||||
|
this.layerGroup.addLayer(circle);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPoints(options: DynmapCircle, latLng: Function, outline: boolean): LatLngExpression[] {
|
||||||
|
const points = [];
|
||||||
|
|
||||||
|
for(let i = 0; i < 360; i++) {
|
||||||
|
const rad = i * Math.PI / 180.0,
|
||||||
|
x = options.radius[0] * Math.sin(rad) + options.location.x,
|
||||||
|
z = options.radius[1] * Math.cos(rad) + options.location.z;
|
||||||
|
|
||||||
|
console.log(x,options.location.y,z, latLng(x, options.location.y, z));
|
||||||
|
|
||||||
|
points.push(latLng(x, options.location.y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(outline && points.length) {
|
||||||
|
points.push(points[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateCircle(id: string, options: DynmapCircle, latLng: Function) {
|
||||||
|
let circle = this.layers.get(id) as L.Polyline,
|
||||||
|
outline = (options.style && options.style.fillOpacity && (options.style.fillOpacity <= 0)) as boolean,
|
||||||
|
points = this.getPoints(options, latLng, outline);
|
||||||
|
|
||||||
|
if (!circle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
circle.setLatLngs(points);
|
||||||
|
circle.redraw();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
122
src/components/map/vector/Lines.vue
Normal file
122
src/components/map/vector/Lines.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {defineComponent, computed} from "@vue/runtime-core";
|
||||||
|
import L, {LatLngExpression} from 'leaflet';
|
||||||
|
import {useStore} from "@/store";
|
||||||
|
import {DynmapLine} from "@/dynmap";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
lines: {
|
||||||
|
type: Object as () => Map<string, DynmapLine>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
layerGroup: {
|
||||||
|
type: Object as () => L.LayerGroup,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const store = useStore(),
|
||||||
|
currentProjection = computed(() => store.state.currentProjection),
|
||||||
|
layers = Object.freeze(new Map()) as Map<string, L.Path>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
layers,
|
||||||
|
currentProjection,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
//FIXME: Prevent unnecessary repositioning when changing worlds
|
||||||
|
currentProjection() {
|
||||||
|
const projection = useStore().state.currentProjection,
|
||||||
|
latLng = (x: number, y: number, z: number) => {
|
||||||
|
return projection.locationToLatLng({x, y, z});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for (const [id, line] of this.lines) {
|
||||||
|
this.updateLine(id, line, latLng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.createLines();
|
||||||
|
},
|
||||||
|
|
||||||
|
unmounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
createLines() {
|
||||||
|
const projection = useStore().state.currentProjection,
|
||||||
|
latLng = (x: number, y: number, z: number) => {
|
||||||
|
return projection.locationToLatLng({x, y, z});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.lines.forEach((line: DynmapLine, id: string) => {
|
||||||
|
this.createLine(id, line, latLng);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
createLine(id: string, options: DynmapLine, latLng: Function) {
|
||||||
|
const points = this.getPoints(options, latLng),
|
||||||
|
line= new L.Polyline(points, options.style);
|
||||||
|
|
||||||
|
if(options.label) {
|
||||||
|
line.bindPopup(() => {
|
||||||
|
const popup = document.createElement('span');
|
||||||
|
|
||||||
|
if (options.popupContent) {
|
||||||
|
popup.classList.add('LinePopup');
|
||||||
|
popup.insertAdjacentHTML('afterbegin', options.popupContent);
|
||||||
|
} else if (options.isHTML) {
|
||||||
|
popup.classList.add('LinePopup');
|
||||||
|
popup.insertAdjacentHTML('afterbegin', options.label);
|
||||||
|
} else {
|
||||||
|
popup.textContent = options.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layers.set(id, line);
|
||||||
|
this.layerGroup.addLayer(line);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPoints(options: DynmapLine, latLng: Function): LatLngExpression[] {
|
||||||
|
const points = [];
|
||||||
|
|
||||||
|
for(let i = 0; i < options.x.length; i++) {
|
||||||
|
points.push(latLng(options.x[i], options.y[i], options.z[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateLine(id: string, options: DynmapLine, latLng: Function) {
|
||||||
|
let line = this.layers.get(id) as L.Polyline,
|
||||||
|
points = this.getPoints(options, latLng);
|
||||||
|
|
||||||
|
if (!line) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line.setLatLngs(points);
|
||||||
|
line.redraw();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
2
src/dynmap.d.ts
vendored
2
src/dynmap.d.ts
vendored
@ -203,7 +203,7 @@ interface DynmapLine {
|
|||||||
interface DynmapCircle {
|
interface DynmapCircle {
|
||||||
location: Coordinate;
|
location: Coordinate;
|
||||||
radius: PointTuple;
|
radius: PointTuple;
|
||||||
style: CircleMarkerOptions;
|
style: PathOptions;
|
||||||
label: string;
|
label: string;
|
||||||
isHTML: boolean;
|
isHTML: boolean;
|
||||||
minZoom?: number;
|
minZoom?: number;
|
||||||
|
Loading…
Reference in New Issue
Block a user