Added flyTo support ; targets players
The implementation forces Vue to attach vanilla event handlers, because their VDom doesn't bubble up and there's no way for it to easily communicate with Astro components. Nanostores aren't an option because .astro files are rendered on the server, so the store can't be used client side (would be nice if it did tho!!!)
This commit is contained in:
@@ -12,177 +12,185 @@ const { markers, players } = $world.get()
|
||||
</div>
|
||||
|
||||
<script lang="ts" define:vars={{ markers, players }}>
|
||||
const mapHeight = 15168;
|
||||
const mapWidth = 14658;
|
||||
const mapHeight = 15168;
|
||||
const mapWidth = 14658;
|
||||
|
||||
const map = L.map('world', {
|
||||
crs: L.CRS.Simple,
|
||||
maxZoom: 12,
|
||||
minZoom: 2.5,
|
||||
zoom: 2.5,
|
||||
zoomSnap: 0,
|
||||
zoomControl: false
|
||||
const map = L.map('world', {
|
||||
crs: L.CRS.Simple,
|
||||
maxZoom: 12,
|
||||
minZoom: 2.5,
|
||||
zoom: 2.5,
|
||||
zoomSnap: 0,
|
||||
zoomControl: false
|
||||
});
|
||||
|
||||
L.control.zoom({
|
||||
position: 'bottomright',
|
||||
}).addTo(map);
|
||||
|
||||
// Layers
|
||||
const layer = L.tileLayer.zoomify('/zoomify/alliance-kaldelienne/{g}/{z}-{x}-{y}.jpg', {
|
||||
width: mapWidth,
|
||||
height: mapHeight,
|
||||
}).addTo(map);
|
||||
|
||||
const layerGroups = {
|
||||
players: L.layerGroup(),
|
||||
capitals: L.layerGroup(),
|
||||
cities: L.layerGroup(),
|
||||
towns: L.layerGroup(),
|
||||
landmarks: L.layerGroup(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Build all markers and their related info
|
||||
*/
|
||||
for (let i = 0; i < markers.length; i++) {
|
||||
const m = markers[i];
|
||||
|
||||
const coords = [m.markerCoords.y, m.markerCoords.x];
|
||||
|
||||
let markerIcon
|
||||
|
||||
switch (m.group) {
|
||||
case "capitals":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/castle.png`,
|
||||
shadowUrl: `icons/castle-shadow.png`,
|
||||
iconSize: [25, 25],
|
||||
shadowSize: [35, 30],
|
||||
iconAnchor: [12.5, 8],
|
||||
shadowAnchor: [11, 12]
|
||||
});
|
||||
break;
|
||||
|
||||
case "cities":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/circle.png`,
|
||||
iconSize: [12, 12],
|
||||
});
|
||||
break;
|
||||
|
||||
case "landmarks":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/monument.png`,
|
||||
shadowUrl: `icons/monument-shadow.png`,
|
||||
iconSize: [18, 18],
|
||||
shadowSize: [32, 14],
|
||||
iconAnchor: [12.5, 8],
|
||||
shadowAnchor: [15, 6]
|
||||
});
|
||||
break;
|
||||
|
||||
case "towns":
|
||||
default:
|
||||
iconKey = "house"
|
||||
break;
|
||||
}
|
||||
|
||||
const marker = L.marker(coords, { icon: markerIcon }).addTo(map);
|
||||
const popupContent = `
|
||||
<b>
|
||||
<a href="${m.link}" target="_blank">
|
||||
${m.title}
|
||||
</a>
|
||||
</b>
|
||||
<br>
|
||||
${m.description}
|
||||
`;
|
||||
marker.bindPopup(popupContent).openPopup();
|
||||
|
||||
const displayTooltip = m.group === 'capitals';
|
||||
|
||||
if (displayTooltip) {
|
||||
L.tooltip({ permanent: true, direction: 'top', offset: [0, 2], content: m.title, className: "capital-name", opacity: 1 }).setLatLng(coords).addTo(map);
|
||||
}
|
||||
|
||||
marker.addTo(layerGroups[m.group])
|
||||
}
|
||||
|
||||
/**
|
||||
* Add player's position marker
|
||||
*/
|
||||
if ( players ) {
|
||||
const playersPosition = [players.markerCoords.y, players.markerCoords.x];
|
||||
|
||||
const playerIcon = L.icon({
|
||||
iconUrl: `icons/location-pin.png`,
|
||||
shadowUrl: `icons/location-pin-shadow.png`,
|
||||
iconSize: [18, 24],
|
||||
shadowSize: [20, 16],
|
||||
iconAnchor: [11, 8],
|
||||
shadowAnchor: [3, 0],
|
||||
});
|
||||
|
||||
L.control.zoom({
|
||||
position: 'bottomright',
|
||||
}).addTo(map);
|
||||
const playerMarker = L.marker(playersPosition, { icon: playerIcon }).addTo(map)
|
||||
playerMarker.addTo(layerGroups['players'])
|
||||
}
|
||||
|
||||
// Layers
|
||||
const layer = L.tileLayer.zoomify('/zoomify/alliance-kaldelienne/{g}/{z}-{x}-{y}.jpg', {
|
||||
width: mapWidth,
|
||||
height: mapHeight,
|
||||
}).addTo(map);
|
||||
map.fitBounds(layer.getBounds());
|
||||
|
||||
const layerGroups = {
|
||||
players: L.layerGroup(),
|
||||
capitals: L.layerGroup(),
|
||||
cities: L.layerGroup(),
|
||||
towns: L.layerGroup(),
|
||||
landmarks: L.layerGroup(),
|
||||
};
|
||||
// L.control.layers({ "base": layer }, layerGroups).addTo(map);
|
||||
|
||||
/**
|
||||
* Build all markers and their related info
|
||||
*/
|
||||
for (let i = 0; i < markers.length; i++) {
|
||||
const m = markers[i];
|
||||
/**
|
||||
* RULER
|
||||
*/
|
||||
/**
|
||||
* Workaround specific to leaflet version
|
||||
* See https://github.com/ljagis/leaflet-measure/issues/171 for details
|
||||
*/
|
||||
L.Control.Measure.include({
|
||||
// set icon on the capture marker
|
||||
_setCaptureMarkerIcon: function () {
|
||||
// disable autopan
|
||||
this._captureMarker.options.autoPanOnFocus = false;
|
||||
|
||||
const coords = [m.markerCoords.y, m.markerCoords.x];
|
||||
// default function
|
||||
this._captureMarker.setIcon(
|
||||
L.divIcon({
|
||||
iconSize: this._map.getSize().multiplyBy(2)
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
let markerIcon
|
||||
|
||||
switch (m.group) {
|
||||
case "capitals":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/castle.png`,
|
||||
shadowUrl: `icons/castle-shadow.png`,
|
||||
iconSize: [25, 25],
|
||||
shadowSize: [35, 30],
|
||||
iconAnchor: [12.5, 8],
|
||||
shadowAnchor: [11, 12]
|
||||
});
|
||||
break;
|
||||
|
||||
case "cities":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/circle.png`,
|
||||
iconSize: [12, 12],
|
||||
});
|
||||
break;
|
||||
|
||||
case "landmarks":
|
||||
markerIcon = L.icon({
|
||||
iconUrl: `icons/monument.png`,
|
||||
shadowUrl: `icons/monument-shadow.png`,
|
||||
iconSize: [18, 18],
|
||||
shadowSize: [32, 14],
|
||||
iconAnchor: [12.5, 8],
|
||||
shadowAnchor: [15, 6]
|
||||
});
|
||||
break;
|
||||
|
||||
case "towns":
|
||||
default:
|
||||
iconKey = "house"
|
||||
break;
|
||||
}
|
||||
|
||||
const marker = L.marker(coords, { icon: markerIcon }).addTo(map);
|
||||
const popupContent = `
|
||||
<b>
|
||||
<a href="${m.link}" target="_blank">
|
||||
${m.title}
|
||||
</a>
|
||||
</b>
|
||||
<br>
|
||||
${m.description}
|
||||
`;
|
||||
marker.bindPopup(popupContent).openPopup();
|
||||
|
||||
const displayTooltip = m.group === 'capitals';
|
||||
|
||||
if (displayTooltip) {
|
||||
L.tooltip({ permanent: true, direction: 'top', offset: [0, 2], content: m.title, className: "capital-name", opacity: 1 }).setLatLng(coords).addTo(map);
|
||||
}
|
||||
|
||||
marker.addTo(layerGroups[m.group])
|
||||
}
|
||||
|
||||
/**
|
||||
* Add player's position marker
|
||||
*/
|
||||
if ( players ) {
|
||||
const playersPosition = [players.markerCoords.y, players.markerCoords.x];
|
||||
|
||||
const playerIcon = L.icon({
|
||||
iconUrl: `icons/location-pin.png`,
|
||||
shadowUrl: `icons/location-pin-shadow.png`,
|
||||
iconSize: [18, 24],
|
||||
shadowSize: [20, 16],
|
||||
iconAnchor: [11, 8],
|
||||
shadowAnchor: [3, 0],
|
||||
});
|
||||
|
||||
const playerMarker = L.marker(playersPosition, { icon: playerIcon }).addTo(map)
|
||||
playerMarker.addTo(layerGroups['players'])
|
||||
}
|
||||
|
||||
map.fitBounds(layer.getBounds());
|
||||
|
||||
// L.control.layers({ "base": layer }, layerGroups).addTo(map);
|
||||
|
||||
/**
|
||||
* RULER
|
||||
*/
|
||||
/**
|
||||
* Workaround specific to leaflet version
|
||||
* See https://github.com/ljagis/leaflet-measure/issues/171 for details
|
||||
*/
|
||||
L.Control.Measure.include({
|
||||
// set icon on the capture marker
|
||||
_setCaptureMarkerIcon: function () {
|
||||
// disable autopan
|
||||
this._captureMarker.options.autoPanOnFocus = false;
|
||||
|
||||
// default function
|
||||
this._captureMarker.setIcon(
|
||||
L.divIcon({
|
||||
iconSize: this._map.getSize().multiplyBy(2)
|
||||
})
|
||||
);
|
||||
const rulerOptions = {
|
||||
position: 'topright',
|
||||
primaryLengthUnit: 'kilometers',
|
||||
secondaryLengthUnit: 'days',
|
||||
primaryAreaUnit: 'hectares',
|
||||
units: {
|
||||
kilometers: {
|
||||
factor: 0.00013,
|
||||
display: 'Kilomètres',
|
||||
},
|
||||
});
|
||||
|
||||
const rulerOptions = {
|
||||
position: 'topright',
|
||||
primaryLengthUnit: 'kilometers',
|
||||
secondaryLengthUnit: 'days',
|
||||
primaryAreaUnit: 'hectares',
|
||||
units: {
|
||||
kilometers: {
|
||||
factor: 0.00013,
|
||||
display: 'Kilomètres',
|
||||
},
|
||||
days: {
|
||||
factor: 0.000002,
|
||||
display: 'Jours de marche',
|
||||
decimals: 1
|
||||
}
|
||||
days: {
|
||||
factor: 0.000002,
|
||||
display: 'Jours de marche',
|
||||
decimals: 1
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const measureControl = L.control.measure(rulerOptions);
|
||||
measureControl.addTo(map);
|
||||
const measureControl = L.control.measure(rulerOptions);
|
||||
measureControl.addTo(map);
|
||||
|
||||
/**
|
||||
* DEBUGS
|
||||
*/
|
||||
map.addEventListener('click', (event) => {
|
||||
let lat = Math.round(event.latlng.lat * 100000) / 100000;
|
||||
let lng = Math.round(event.latlng.lng * 100000) / 100000;
|
||||
console.log(lat, lng);
|
||||
})
|
||||
/**
|
||||
* Flying to points of interests
|
||||
*/
|
||||
document.addEventListener('fly-to', (e) => {
|
||||
const targetCoords = e.detail
|
||||
map.flyTo([targetCoords.y, targetCoords.x], 5)
|
||||
})
|
||||
|
||||
/**
|
||||
* DEBUGS
|
||||
*/
|
||||
map.addEventListener('click', (event) => {
|
||||
let lat = Math.round(event.latlng.lat * 100000) / 100000;
|
||||
let lng = Math.round(event.latlng.lng * 100000) / 100000;
|
||||
console.log(lat, lng);
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user