Layers for POI in web client and list of players.

This commit is contained in:
Raimund Renkert 2022-03-04 16:15:15 +01:00
parent 5de40d6df3
commit c01ff0bdbf
3 changed files with 274 additions and 8 deletions

View File

@ -15,6 +15,56 @@
<v-list-item-title>Players</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox v-model="buildingsLayer"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
Buildings</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox v-model="poiLayer"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Points of Interest</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox v-model="travelnetLayer"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Travelnet</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox v-model="otherLayer"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Other</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider></v-divider>
<v-list-item>
<v-list-item-content>
<v-list-item-title style="font-weight:bold;">Players</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item
v-for="(item, i) in players"
:key="i"
>
<v-list-item-content>
<v-list-item-title v-text="item.properties.name" />
</v-list-item-content>
<v-list-item-action v-if="playersLayer">
<v-icon @click.stop="goToPlayer(item)">fa-crosshairs</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar :clipped-left="true" fixed app>
@ -120,11 +170,19 @@ export default {
mounted() {
fetch("players").then(response => response.json().then((data) => {
this.$store.commit("setPlayers", data);
}))
}));
fetch("poi").then(response => response.json().then((data) => {
this.$store.commit("setPointFeatures", data);
}));
},
methods: {
refreshContent() {
this.$store.dispatch("manualUpdate");
},
goToPlayer(player) {
console.log(player);
const coords = [player.geometry.coordinates[1], player.geometry.coordinates[0]];
this.$store.commit("setMapCenter", coords)
}
}
}

View File

@ -1,7 +1,27 @@
<template>
<v-container fluid style="height: 100%; padding: 0px">
<l-map @mousemove="update" ref="map" style="height: 100%" :zoom="zoom" :center="center" :worldCopyJump="worldCopyJump" :crs="crs" :options="mapOptions">
<l-map @mousemove="update" ref="map" style="height: 100%" :zoom="zoom" :center="mapCenter" :worldCopyJump="worldCopyJump" :crs="crs" :options="mapOptions">
<l-tile-layer ref="baseLayer" :url="url" :attribution="attribution" :tms="tms" continuousWorld="false" minZoom=0 :noWrap="noWrap" :options="layerOptions"></l-tile-layer>
<l-marker-cluster v-if="buildingsLayer" :options="buildingClusterOptions">
<l-marker v-for="f in buildingFeatures" :key="f.id" :lat-lng="f.pos" :icon="iconBlue">
<l-popup>{{f.text}}</l-popup>
</l-marker>
</l-marker-cluster>
<l-marker-cluster v-if="travelnetLayer" :options="travelnetClusterOptions">
<l-marker v-for="f in travelnetFeatures" :key="f.id" :lat-lng="f.pos" :icon="iconYellow">
<l-popup>{{f.text}}</l-popup>
</l-marker>
</l-marker-cluster>
<l-marker-cluster v-if="poiLayer" :options="poiClusterOptions">
<l-marker v-for="f in poiFeatures" :key="f.id" :lat-lng="f.pos" :icon="iconRed">
<l-popup>{{f.text}}</l-popup>
</l-marker>
</l-marker-cluster>
<l-marker-cluster v-if="otherLayer" :options="otherClusterOptions">
<l-marker v-for="f in otherFeatures" :key="f.id" :lat-lng="f.pos" :icon="iconGreen">
<l-popup>{{f.text}}</l-popup>
</l-marker>
</l-marker-cluster>
<div v-if="playersLayer">
<l-marker v-for="p in players" :key="p.name" :lat-lng="flipCoordinates(p.geometry.coordinates)" :icon="iconPlayer">
<l-popup>{{p.properties.name}}</l-popup>
@ -44,29 +64,107 @@ export default {
url: 'map/{z}/{x}/{y}.png',
zoom: 3,
noWrap: true,
center: [0,0],
worldCopyJump: false,
crs: ownCRS,
tms: true,
attribution: process.env.VUE_APP_TITLE,
features: [],
iconPlayer: new L.Icon({
iconUrl: require('@/assets/marker-player.png'),
iconSize: [25, 41],
iconAnchor: [12, 41],
iconPlayer: L.divIcon({
html: '<div class="divIconOrange"></div><div class="iconFontPlayer"><i class="fas fa-walking"></i> </div>',
popupAnchor: [1, -34],
iconSize: L.point(0, 0)
}),
iconBlue: L.divIcon({
html: '<div class="divIconBlue"></div><div class="iconFont"><i class="fas fa-building"></i> </div>',
popupAnchor: [1, -34],
iconSize: L.point(0, 0)
}),
iconRed: L.divIcon({
html: '<div class="divIconRed"></div><div class="iconFont"><i class="fas fa-hand-pointer"></i> </div>',
popupAnchor: [1, -34],
iconSize: L.point(0, 0)
}),
iconYellow: L.divIcon({
html: '<div class="divIconYellow"></div><div class="iconFont"><i class="fas fa-route"></i> </div>',
popupAnchor: [1, -34],
iconSize: L.point(0, 0)
}),
iconGreen: L.divIcon({
html: '<div class="divIconGreen"></div><div class="iconFont"><i class="fas fa-bullseye"></i> </div>',
popupAnchor: [1, -34],
iconSize: L.point(0, 0)
}),
buildingClusterOptions: {
maxClusterRadius: 50,
iconCreateFunction: (cluster) => {
return L.divIcon({ html: '<div class="divIconBlue"></div><div class="myMarkerCluster">' +
cluster.getChildCount() +
'</div>',
iconSize: L.point(0, 0) });
},
},
travelnetClusterOptions: {
maxClusterRadius: 50,
iconCreateFunction: (cluster) => {
return L.divIcon({ html: '<div class="divIconYellow"></div><div class="myMarkerCluster">' +
cluster.getChildCount() +
'</div>',
iconSize: L.point(0, 0) });
},
},
poiClusterOptions: {
maxClusterRadius: 50,
iconCreateFunction: (cluster) => {
return L.divIcon({ html: '<div class="divIconRed"></div><div class="myMarkerCluster">' +
cluster.getChildCount() +
'</div>',
iconSize: L.point(0, 0) });
},
},
otherClusterOptions: {
maxClusterRadius: 50,
iconCreateFunction: (cluster) => {
return L.divIcon({ html: '<div class="divIconGreen"></div><div class="myMarkerCluster">' +
cluster.getChildCount() +
'</div>',
iconSize: L.point(0, 0) });
},
}
}
},
computed: {
buildingFeatures() {
return this.$store.state.pointFeatures.filter(f => f.type === 'Building');
},
travelnetFeatures() {
return this.$store.state.pointFeatures.filter(f => f.type === 'Travelnet')
},
poiFeatures() {
return this.$store.state.pointFeatures.filter(f => f.type === 'Point of Interest')
},
otherFeatures() {
return this.$store.state.pointFeatures.filter(f => f.type === 'Other')
},
players() {
console.log(this.$store.state.players);
return this.$store.state.players;
},
...mapState({
mapCenter: state => state.mapCenter,
features: state => state.pointFeatures,
autoUpdate: state => state.autoUpdate,
playersLayer: state => state.playersLayer,
buildingsLayer: state => state.buildingsLayer,
poiLayer: state => state.poiLayer,
travelnetLayer: state => state.travelnetLayer,
otherLayer: state => state.otherLayer,
}),
},
mounted() {
this.$nextTick(function () {
console.log(this.$refs.baseLayer);
})
},
methods: {
update(evt) {
this.$store.commit('updateCoordinates', [evt.latlng.lat, evt.latlng.lng])
@ -83,4 +181,89 @@ export default {
color: #f5f5f5;
background-color: #424242;
}
.iconFontPlayer {
font-size: medium;
width: 17px;
height: 17px;
color: rgb(58, 58, 58);
position: absolute;
top: -41px;
left: -9px;
font-weight: bold;
text-align: center;
border: 0px solid #666;
}
.iconFont {
width: 17px;
height: 17px;
color: rgb(58, 58, 58);
position: absolute;
top: -38px;
left: -9px;
font-weight: bold;
text-align: center;
border: 0px solid #666;
}
.myMarkerCluster {
border-radius: 49%;
width: 18px;
height: 18px;
background-color: #616160;
color: white;
position: absolute;
top: -38px;
left: -10px;
font-weight: bold;
text-align: center;
}
.divIconBlue {
width: 24px;
height: 40px;
position: absolute;
top: -42px;
left: -13px;
line-height: 40px;
background-image: url("@/assets/marker-icon-blue.png");
text-align: center;
}
.divIconYellow {
width: 24px;
height: 40px;
position: absolute;
top: -42px;
left: -13px;
line-height: 40px;
background-image: url("@/assets/marker-icon-yellow.png");
text-align: center;
}
.divIconRed {
width: 24px;
height: 40px;
position: absolute;
top: -42px;
left: -13px;
line-height: 40px;
background-image: url("@/assets/marker-icon-red.png");
text-align: center;
}
.divIconGreen {
width: 24px;
height: 40px;
position: absolute;
top: -42px;
left: -13px;
line-height: 40px;
background-image: url("@/assets/marker-icon-green.png");
text-align: center;
}
.divIconOrange {
width: 24px;
height: 40px;
position: absolute;
top: -42px;
left: -13px;
line-height: 40px;
background-image: url("@/assets/marker-icon-orange.png");
text-align: center;
}
</style>

View File

@ -13,7 +13,9 @@ export default new Vuex.Store({
poiLayer: true,
travelnetLayer: true,
otherLayer: true,
players: []
players: [],
mapCenter: [0, 0],
pointFeatures: [],
},
mutations: {
@ -44,6 +46,12 @@ export default new Vuex.Store({
setPlayerState(state, value) {
const p = state.players.find(p => p.name === value.name)
p.online = value.state;
},
setMapCenter(state, value) {
state.mapCenter = value;
},
setPointFeatures(state, value) {
state.pointFeatures = value;
}
},
@ -73,6 +81,9 @@ export default new Vuex.Store({
fetch("players").then(response => response.json().then((data) => {
commit("setPlayers", data);
}));
fetch("poi").then(response => response.json().then((data) => {
commit("setPointFeatures", data);
}));
},
runAutoUpdate: function({ commit, state, dispatch}) {
@ -121,6 +132,20 @@ export default new Vuex.Store({
commit('setPlayers', msg.players);
}
if (msg.poi) {
console.log(msg.poi)
let points = [];
for (let i = 0; i < msg.poi.length; i++) {
points.push({
id: i,
pos: [msg.poi[i].pos.x, msg.poi[i].pos.z],
text: msg.poi[i].text,
type: msg.poi[i].type,
});
}
commit("setPointFeatures", points);
}
var tilesData = msg.tiles;
if (!tilesData) {
return;