Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ed0aad6f0 | ||
|
|
2591c72ddd | ||
|
|
90084c1d37 | ||
|
|
e07ee03aee | ||
|
|
482de67442 | ||
|
|
4f3f37f452 | ||
|
|
73a02da0e8 | ||
|
|
dcbcd6f038 | ||
|
|
0b78e84a96 | ||
|
|
9c670a8b78 | ||
|
|
2f58f45954 | ||
|
|
d695e60a2f | ||
|
|
f35d0e23b8 | ||
|
|
54a4f8bdf5 | ||
|
|
c8e8f61f8a | ||
|
|
4e347e7d7d | ||
|
|
6086161a78 | ||
|
|
3a6abdaf93 | ||
|
|
27b3dfa52d | ||
|
|
92c7846247 |
@@ -2,4 +2,4 @@
|
|||||||
Repository for interactive maps using Leim's Wiki data
|
Repository for interactive maps using Leim's Wiki data
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
Live demo available at https://maps.alexcreates.fr/
|
Live demo available at https://maps.alexcreates.fr
|
||||||
6434
package-lock.json
generated
16
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "leim-maps",
|
"name": "leim-maps",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.0.0",
|
"version": "1.3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"start": "astro dev",
|
"start": "astro dev",
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/sitemap": "^3.0.4",
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@astrojs/vue": "^4.0.8",
|
"@astrojs/vue": "^5.0.3",
|
||||||
"@types/leaflet": "^1.9.8",
|
"@types/leaflet": "^1.9.15",
|
||||||
"@vueuse/core": "^10.7.1",
|
"@vueuse/core": "^12.2.0",
|
||||||
"astro": "^4.1.2",
|
"astro": "^5.1.1",
|
||||||
"vue": "^3.4.14"
|
"vue": "^3.5.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"sass": "^1.68.0"
|
"sass": "^1.83.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5519
pnpm-lock.yaml
generated
Normal file
BIN
public/icon/graduation-cap-shadow.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/icon/graduation-cap.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
public/images/cover/Académie_Centrale_Kaldélienne.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/cover/Ambrose.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/cover/Cantane.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/images/cover/Cordouac.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
public/images/cover/Horfer.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/images/cover/Port-brisé.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/cover/Port_de_Borélis.jpeg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/images/cover/Soubreciel.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/images/cover/Tourgrise.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
public/images/cover/Tours_des_Cages.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
public/images/cover/Willeau.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
@@ -11,9 +11,83 @@
|
|||||||
.leaflet-popup-pane {
|
.leaflet-popup-pane {
|
||||||
.leaflet-popup-content-wrapper {
|
.leaflet-popup-content-wrapper {
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
|
overflow: clip;
|
||||||
|
|
||||||
.leaflet-popup-content {
|
.leaflet-popup-content {
|
||||||
margin: .65rem 1.3rem .65rem .9rem;
|
min-width: 20rem;
|
||||||
|
margin: 1rem;
|
||||||
|
|
||||||
|
figure {
|
||||||
|
position: relative;
|
||||||
|
margin-inline: -1.1rem;
|
||||||
|
margin-top: -1.1rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
|
||||||
|
&.landscape {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
min-width: 20rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.portrait {
|
||||||
|
aspect-ratio: 15 / 16;
|
||||||
|
min-width: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 10;
|
||||||
|
// Make a linear gradient from top to bottom, from transparent to black
|
||||||
|
background: linear-gradient(to bottom, transparent 70%, var(--black) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption cite {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 85%;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 600;
|
||||||
|
bottom: .5rem;
|
||||||
|
right: 1rem;
|
||||||
|
color: var(--white);
|
||||||
|
z-index: 20;
|
||||||
|
opacity: .6;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: .2s;
|
||||||
|
transition-timing-function: cubic-bezier(0.23, 1, 0.320, 1);
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding-right: 0;
|
||||||
|
color: var(--white);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: .15rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--blue-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
figcaption cite {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -58,11 +132,11 @@
|
|||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
|
|
||||||
|
@include text.stroke(2, #18181b);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include text.stroke(2, #18181b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@use 'sass:list';
|
||||||
|
|
||||||
/// Stroke font-character
|
/// Stroke font-character
|
||||||
/// @param {Integer} $stroke - Stroke width
|
/// @param {Integer} $stroke - Stroke width
|
||||||
/// @param {Color} $color - Stroke color
|
/// @param {Color} $color - Stroke color
|
||||||
@@ -8,7 +10,7 @@
|
|||||||
|
|
||||||
@for $i from $from through $stroke {
|
@for $i from $from through $stroke {
|
||||||
@for $j from $from through $stroke {
|
@for $j from $from through $stroke {
|
||||||
$shadow: append($shadow, $i*1px $j*1px 0 $color, comma);
|
$shadow: list.append($shadow, $i*1px $j*1px 0 $color, comma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ for (let i = 0; i < markers.length; i++) {
|
|||||||
const coords = [convertYToScale(m.markerCoords.y), convertXToScale(m.markerCoords.x)]
|
const coords = [convertYToScale(m.markerCoords.y), convertXToScale(m.markerCoords.x)]
|
||||||
|
|
||||||
let markerIcon
|
let markerIcon
|
||||||
|
let markerIconOverride
|
||||||
|
|
||||||
switch (m.group) {
|
switch (m.group) {
|
||||||
case "capitals":
|
case "capitals":
|
||||||
@@ -154,23 +155,56 @@ for (let i = 0; i < markers.length; i++) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const marker = L.marker(coords, { icon: markerIcon }).addTo(map)
|
// Handle icon override if it's specified
|
||||||
|
markerIconOverride = markerIcon
|
||||||
|
if (m.icon) {
|
||||||
|
markerIconOverride = L.icon({
|
||||||
|
iconUrl: `icon/${m.icon}.png`,
|
||||||
|
shadowUrl: `icon/${m.icon}-shadow.png`,
|
||||||
|
iconSize: [25, 25],
|
||||||
|
shadowSize: [35, 30],
|
||||||
|
iconAnchor: [12.5, 8],
|
||||||
|
shadowAnchor: [11, 12]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = L.marker(coords, { icon: markerIconOverride }).addTo(map)
|
||||||
|
|
||||||
|
// Build popup content
|
||||||
let popupContent = ""
|
let popupContent = ""
|
||||||
|
|
||||||
|
if (m.cover && m.coverAuthor && m.coverLink) {
|
||||||
|
const figureClass = m.coverPortrait ? 'portrait' : 'landscape';
|
||||||
|
const figureWidth = m.coverPortrait ? 210 : 420;
|
||||||
|
|
||||||
|
popupContent += `
|
||||||
|
<figure class="${figureClass}">
|
||||||
|
<img src="/images/cover/${m.cover}" alt="${m.title}" width="${figureWidth}" loading="lazy" />
|
||||||
|
<figcaption>
|
||||||
|
<cite>par <a href="${m.coverLink}" target="_blank">${m.coverAuthor}</a></cite>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
if (m.link) {
|
if (m.link) {
|
||||||
popupContent = `
|
popupContent += `
|
||||||
<a href="${m.link}" target="_blank" class="title">
|
<a href="${m.link}" target="_blank" class="title">
|
||||||
${m.title}
|
${m.title}
|
||||||
</a>
|
</a>
|
||||||
<p>${m.description}</p>
|
|
||||||
`
|
`
|
||||||
} else {
|
} else {
|
||||||
popupContent = `
|
popupContent += `
|
||||||
<strong class="title">
|
<strong class="title">
|
||||||
${m.title}
|
${m.title}
|
||||||
</strong>
|
</strong>
|
||||||
<p>${m.description}</p>
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m.description) {
|
||||||
|
popupContent += `<p>${m.description}</p>`
|
||||||
|
}
|
||||||
|
|
||||||
marker.bindPopup(popupContent).openPopup()
|
marker.bindPopup(popupContent).openPopup()
|
||||||
|
|
||||||
const displayTooltip = m.group === 'capitals'
|
const displayTooltip = m.group === 'capitals'
|
||||||
@@ -443,6 +477,84 @@ function removeCustomMarker(marker, markerTitle) {
|
|||||||
saveCustomMarkers()
|
saveCustomMarkers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL PARAMETERS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From the leaflet setup, get a working param config
|
||||||
|
*
|
||||||
|
* @returns Latitude, Longitude and zoom level of the map
|
||||||
|
*/
|
||||||
|
function getURLFromSetup() {
|
||||||
|
const centerOfMap = map.getCenter()
|
||||||
|
|
||||||
|
const lat = centerOfMap.lat
|
||||||
|
const lon = centerOfMap.lng
|
||||||
|
const zoom = parseFloat(map.getZoom().toFixed(1))
|
||||||
|
|
||||||
|
return { lat, lon, zoom }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get leaflet coords from URL params
|
||||||
|
*
|
||||||
|
* @returns URLSearchParams
|
||||||
|
*/
|
||||||
|
function getCoordsSetupFromURL() {
|
||||||
|
const params = new URL(document.location).searchParams
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the params in the URL can be parsed as leaflet coordinates
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function hasInitialSetup() {
|
||||||
|
const params = new URL(document.location).searchParams
|
||||||
|
|
||||||
|
return params.has('lat') && params.has('lon')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to refresh the URL params
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
function setupToURL() {
|
||||||
|
const setup = getURLFromSetup()
|
||||||
|
|
||||||
|
const newParams = new URLSearchParams(setup)
|
||||||
|
const newUrl = new URL(window.location.href)
|
||||||
|
newUrl.search = newParams.toString()
|
||||||
|
|
||||||
|
window.history.replaceState(null, '', newUrl.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the URL params to setup the leaflet map
|
||||||
|
*/
|
||||||
|
function setupFromURL() {
|
||||||
|
const setup = getCoordsSetupFromURL()
|
||||||
|
|
||||||
|
map.setView({ lat: setup.get('lat'), lng: setup.get('lon') }, setup.get('zoom') | minZoom, { animate: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the map has initial params in the URL
|
||||||
|
// If not, just setup the default URL
|
||||||
|
if (hasInitialSetup()) {
|
||||||
|
setupFromURL()
|
||||||
|
} else {
|
||||||
|
setupToURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the map stops moving, update the URL to keep it up to date
|
||||||
|
map.on('moveend', () => {
|
||||||
|
setupToURL()
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UTILITIES
|
* UTILITIES
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 83.6,
|
"x": 83.6,
|
||||||
"y": -185.2
|
"y": -185.2
|
||||||
}
|
},
|
||||||
|
"cover": "Ambrose.jpg",
|
||||||
|
"coverAuthor": "Claudio Pilia",
|
||||||
|
"coverLink": "https://pilia-art.com/portfolio-item/game-of-thrones-the-city-of-tyrosh/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "capitals",
|
"group": "capitals",
|
||||||
@@ -18,7 +21,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 133.46875,
|
"x": 133.46875,
|
||||||
"y": -146.0625
|
"y": -146.0625
|
||||||
}
|
},
|
||||||
|
"cover": "Cordouac.jpg",
|
||||||
|
"coverAuthor": "Vincent Joyal",
|
||||||
|
"coverLink": "https://www.artstation.com/artwork/6B0b0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "capitals",
|
"group": "capitals",
|
||||||
@@ -38,7 +44,11 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 132.26953,
|
"x": 132.26953,
|
||||||
"y": -98.19141
|
"y": -98.19141
|
||||||
}
|
},
|
||||||
|
"cover": "Tourgrise.png",
|
||||||
|
"coverAuthor": "saya kuroha",
|
||||||
|
"coverLink": "https://www.pixiv.net/en/artworks/83793821",
|
||||||
|
"coverPortrait": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "capitals",
|
"group": "capitals",
|
||||||
@@ -68,7 +78,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 168.39491,
|
"x": 168.39491,
|
||||||
"y": -109.13376
|
"y": -109.13376
|
||||||
}
|
},
|
||||||
|
"cover": "Port-brisé.jpg",
|
||||||
|
"coverAuthor": "JC Jongwon Park",
|
||||||
|
"coverLink": "https://www.artstation.com/artwork/okmQL"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "capitals",
|
"group": "capitals",
|
||||||
@@ -108,7 +121,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 204.42515,
|
"x": 204.42515,
|
||||||
"y": -226.85883
|
"y": -226.85883
|
||||||
}
|
},
|
||||||
|
"cover": "Soubreciel.jpg",
|
||||||
|
"coverAuthor": "Tony Andreas Rudolph",
|
||||||
|
"coverLink": "https://www.artstation.com/artwork/EB84"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "capitals",
|
"group": "capitals",
|
||||||
@@ -148,7 +164,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 138.44531,
|
"x": 138.44531,
|
||||||
"y": -51.54687
|
"y": -51.54687
|
||||||
}
|
},
|
||||||
|
"cover": "Port_de_Borélis.jpeg",
|
||||||
|
"coverAuthor": "Anton Bezrukov",
|
||||||
|
"coverLink": "https://www.artstation.com/artwork/oODL5B"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "cities",
|
"group": "cities",
|
||||||
@@ -188,7 +207,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 197.3492280183025,
|
"x": 197.3492280183025,
|
||||||
"y": -210.87224307207197
|
"y": -210.87224307207197
|
||||||
}
|
},
|
||||||
|
"cover": "Cantane.jpg",
|
||||||
|
"coverAuthor": "Andreas Roller",
|
||||||
|
"coverLink": "https://en.wikipedia.org/wiki/Andreas_Roller"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "cities",
|
"group": "cities",
|
||||||
@@ -198,7 +220,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 185.57431,
|
"x": 185.57431,
|
||||||
"y": -229.08588
|
"y": -229.08588
|
||||||
}
|
},
|
||||||
|
"cover": "Horfer.jpg",
|
||||||
|
"coverAuthor": "Nele-Diel",
|
||||||
|
"coverLink": "https://www.deviantart.com/nele-diel/art/City-in-the-Lowlands-693529688"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "cities",
|
"group": "cities",
|
||||||
@@ -528,7 +553,10 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 107.50352,
|
"x": 107.50352,
|
||||||
"y": -67.36631
|
"y": -67.36631
|
||||||
}
|
},
|
||||||
|
"cover": "Willeau.jpg",
|
||||||
|
"coverAuthor": "Inconnu",
|
||||||
|
"coverLink": "https://www.hebus.com/image-339033.html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "cities",
|
"group": "cities",
|
||||||
@@ -587,7 +615,11 @@
|
|||||||
"markerCoords": {
|
"markerCoords": {
|
||||||
"x": 168.31641,
|
"x": 168.31641,
|
||||||
"y": -60.54297
|
"y": -60.54297
|
||||||
}
|
},
|
||||||
|
"cover": "Tours_des_Cages.jpg",
|
||||||
|
"coverAuthor": "25kartinok",
|
||||||
|
"coverLink": "https://www.deviantart.com/25kartinok/art/the-dark-tower-700231527",
|
||||||
|
"coverPortrait": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "landmarks",
|
"group": "landmarks",
|
||||||
@@ -784,6 +816,97 @@
|
|||||||
"x": 105.79962111804268,
|
"x": 105.79962111804268,
|
||||||
"y": -82.40552057309549
|
"y": -82.40552057309549
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Faculté de Magie Appliquée",
|
||||||
|
"description": "Établissement d'enseignements arcaniques tout public, mais à la qualité lacunaire.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Facult%C3%A9_de_Magie_Appliqu%C3%A9e",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 103.96761286182101,
|
||||||
|
"y": -79.90785827537563
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Académie Artistique Arcanique",
|
||||||
|
"description": "Institut d'apprentissage public centré sur les arts.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Acad%C3%A9mie_Artistique_Arcanique",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 75.84445789595449,
|
||||||
|
"y": -199.14437153165204
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Académie Centrale Kaldélienne",
|
||||||
|
"description": "Une des plus grandes académies dispensant des cours de magie de l'Alliance. L'examen d'entrée est public, mais les coûts de scolarité restent à la charge des étudiants.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Acad%C3%A9mie_Centrale_Kald%C3%A9lienne",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 83.80737652386473,
|
||||||
|
"y": -184.52963682119173
|
||||||
|
},
|
||||||
|
"cover": "Académie_Centrale_Kaldélienne.jpg",
|
||||||
|
"coverAuthor": "Pengzhen Zhang",
|
||||||
|
"coverLink": "https://www.artstation.com/artwork/zAOWNd",
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Grande Maison de Flamberge",
|
||||||
|
"description": "La plus prestigieuse école des Terres de Syaltha. La Grande Maison est une des rares entités à certifier les sal'kayas.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Grande_Maison_de_Flamberge",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 302.23491236190273,
|
||||||
|
"y": -110.07337124956246
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Haute-École de Magistrature Cordouenne",
|
||||||
|
"description": "Institut de l'Alliance formant les magistrats, juges et politiciens de demain.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Haute-%C3%89cole_de_Magistrature_Cordouenne",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 131.07900289783518,
|
||||||
|
"y": -148.801890020031
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Institut du Fer Blanc",
|
||||||
|
"description": "Première école militaire de l'Alliance Kaldélienne.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Institut_du_Fer_Blanc",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 140.3159943633407,
|
||||||
|
"y": -191.78102982328744
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "Maison d'Études de Tourgrise",
|
||||||
|
"description": "Établissement pluridisciplinaires axé vers les études de législations mais possèdant un cursus d'études arcaniques général.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/Maison_d%27%C3%89tudes_de_Tourgrise",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 132.82148271354282,
|
||||||
|
"y": -98.7924395350658
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "landmarks",
|
||||||
|
"title": "École des Arts Spirituels",
|
||||||
|
"description": "Institut privé spécialisé dans les maîtrises des arcanes spirituelles.",
|
||||||
|
"link": "https://alexcreates.fr/leim/index.php/%C3%89cole_des_Arts_Spirituels",
|
||||||
|
"markerCoords": {
|
||||||
|
"x": 124.8585640856326,
|
||||||
|
"y": -95.86995303475213
|
||||||
|
},
|
||||||
|
"icon": "graduation-cap"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -31,10 +31,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const hasQuery = computed(() => q.value.length > 0)
|
const hasQuery = computed(() => q.value.length > 0)
|
||||||
const shouldBeActive = computed(() =>
|
const shouldBeActive = computed(() => hasQuery.value || currentSearchMode.value !== "query")
|
||||||
(hasQuery.value && currentSearchMode.value === "query" && isComponentFocused.value)
|
|
||||||
|| currentSearchMode.value !== "query"
|
|
||||||
)
|
|
||||||
|
|
||||||
const q = ref<string>("")
|
const q = ref<string>("")
|
||||||
|
|
||||||
@@ -223,13 +220,22 @@ function resetAllFields(actionAfter?: "focusAfter") {
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
:title="m.group === 'quests' ? 'Voir la quête' : 'Visiter ce lieu'"
|
:title="m.group === 'quests' ? 'Voir la quête' : 'Visiter ce lieu'"
|
||||||
>
|
>
|
||||||
<span class="title">{{ m.title }}</span>
|
<img v-if="m.cover && !m.coverPortrait" :src="`/images/cover/${m.cover}`" :alt="m.title" width="300" />
|
||||||
|
|
||||||
<div class="desc" v-html="m.description"></div>
|
<div class="content-wrapper">
|
||||||
|
<span class="title">{{ m.title }}</span>
|
||||||
|
|
||||||
<svg v-if="m.group === 'quests'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M231.22,59.44l-80,168a8,8,0,1,1-14.44-6.88L165.62,160H32a8,8,0,0,1-5.88-13.43l42.56-46.1L26.59,61.9A8,8,0,0,1,32,48H224a8,8,0,0,1,7.22,11.44Z"/></svg>
|
<div class="desc" v-html="m.description"></div>
|
||||||
<svg v-else-if="m.group === 'capitals'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M200,24h-8a16,16,0,0,0-16,16V56H148V40a16,16,0,0,0-16-16h-8a16,16,0,0,0-16,16V56H80V40A16,16,0,0,0,64,24H56A16,16,0,0,0,40,40V84.69A15.86,15.86,0,0,0,44.69,96L56,107.31V216a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V107.31L211.31,96A15.86,15.86,0,0,0,216,84.69V40A16,16,0,0,0,200,24ZM152,216H104V152a24,24,0,0,1,48,0Z"/></svg>
|
|
||||||
<svg v-else-if="m.group === 'landmarks'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M208,80a8,8,0,0,0-8,8v16H188.85L184,55.2A8,8,0,0,0,181.31,50h0L138.44,11.88l-.2-.17a16,16,0,0,0-20.48,0l-.2.17L74.68,50v0A7.93,7.93,0,0,0,72,55.2L67.15,104H56V88a8,8,0,0,0-16,0v24a8,8,0,0,0,8,8H65.54l-9.47,94.48A16,16,0,0,0,72,232H184a16,16,0,0,0,15.92-17.56L190.46,120H208a8,8,0,0,0,8-8V88A8,8,0,0,0,208,80ZM87.24,64h81.52l4,40H136V88a8,8,0,0,0-16,0v16H83.23ZM72,216l4.81-48H179.19L184,216Z"/></svg>
|
<div v-if="m.icon">
|
||||||
|
<svg v-if="m.icon === 'graduation-cap'" xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 256 256"><path d="M251.76,88.94l-120-64a8,8,0,0,0-7.52,0l-120,64a8,8,0,0,0,0,14.12L32,117.87v48.42a15.91,15.91,0,0,0,4.06,10.65C49.16,191.53,78.51,216,128,216a130,130,0,0,0,48-8.76V240a8,8,0,0,0,16,0V199.51a115.63,115.63,0,0,0,27.94-22.57A15.91,15.91,0,0,0,224,166.29V117.87l27.76-14.81a8,8,0,0,0,0-14.12ZM128,200c-43.27,0-68.72-21.14-80-33.71V126.4l76.24,40.66a8,8,0,0,0,7.52,0L176,143.47v46.34C163.4,195.69,147.52,200,128,200Zm80-33.75a97.83,97.83,0,0,1-16,14.25V134.93l16-8.53ZM188,118.94l-.22-.13-56-29.87a8,8,0,0,0-7.52,14.12L171,128l-43,22.93L25,96,128,41.07,231,96Z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<svg v-if="m.group === 'quests'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M231.22,59.44l-80,168a8,8,0,1,1-14.44-6.88L165.62,160H32a8,8,0,0,1-5.88-13.43l42.56-46.1L26.59,61.9A8,8,0,0,1,32,48H224a8,8,0,0,1,7.22,11.44Z"/></svg>
|
||||||
|
<svg v-else-if="m.group === 'capitals'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M200,24h-8a16,16,0,0,0-16,16V56H148V40a16,16,0,0,0-16-16h-8a16,16,0,0,0-16,16V56H80V40A16,16,0,0,0,64,24H56A16,16,0,0,0,40,40V84.69A15.86,15.86,0,0,0,44.69,96L56,107.31V216a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V107.31L211.31,96A15.86,15.86,0,0,0,216,84.69V40A16,16,0,0,0,200,24ZM152,216H104V152a24,24,0,0,1,48,0Z"/></svg>
|
||||||
|
<svg v-else-if="m.group === 'landmarks'" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M208,80a8,8,0,0,0-8,8v16H188.85L184,55.2A8,8,0,0,0,181.31,50h0L138.44,11.88l-.2-.17a16,16,0,0,0-20.48,0l-.2.17L74.68,50v0A7.93,7.93,0,0,0,72,55.2L67.15,104H56V88a8,8,0,0,0-16,0v24a8,8,0,0,0,8,8H65.54l-9.47,94.48A16,16,0,0,0,72,232H184a16,16,0,0,0,15.92-17.56L190.46,120H208a8,8,0,0,0,8-8V88A8,8,0,0,0,208,80ZM87.24,64h81.52l4,40H136V88a8,8,0,0,0-16,0v16H83.23ZM72,216l4.81-48H179.19L184,216Z"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Custom marker actions -->
|
<!-- Custom marker actions -->
|
||||||
@@ -399,6 +405,12 @@ function resetAllFields(actionAfter?: "focusAfter") {
|
|||||||
|
|
||||||
li {
|
li {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
border-radius: .5rem;
|
||||||
|
overflow: clip;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover:not(:has(a:hover)) {
|
&:hover:not(:has(a:hover)) {
|
||||||
background-color: var(--slate-100);
|
background-color: var(--slate-100);
|
||||||
@@ -411,11 +423,24 @@ function resetAllFields(actionAfter?: "focusAfter") {
|
|||||||
.search-item {
|
.search-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: .4rem .25em;
|
|
||||||
padding-right: 2.75rem;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border-radius: .5rem;
|
||||||
outline-offset: -1px;
|
outline-offset: -1px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 15dvh;
|
||||||
|
max-height: 15vh;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrapper {
|
||||||
|
position: relative;
|
||||||
|
padding: .4rem .5em .6rem;
|
||||||
|
padding-right: 2.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.title,
|
.title,
|
||||||
.desc {
|
.desc {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ function emitCategorySwitch(newCategory: MapMarkerGroup) {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tag-list {
|
.tag-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
margin-top: .5rem;
|
margin-top: .5rem;
|
||||||
|
|
||||||
@@ -124,6 +125,7 @@ function emitCategorySwitch(newCategory: MapMarkerGroup) {
|
|||||||
border: 1px solid var(--slate-400);
|
border: 1px solid var(--slate-400);
|
||||||
border-radius: 100vmax;
|
border-radius: 100vmax;
|
||||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
||||||
|
white-space: nowrap;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: .2rem solid transparent;
|
outline: .2rem solid transparent;
|
||||||
|
|||||||
1
src/env.d.ts
vendored
@@ -1 +1,2 @@
|
|||||||
|
/// <reference path="../.astro/types.d.ts" />
|
||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
|
|||||||
@@ -45,5 +45,5 @@ const { title } = Astro.props;
|
|||||||
</html>
|
</html>
|
||||||
|
|
||||||
<style lang="scss" is:global>
|
<style lang="scss" is:global>
|
||||||
@import '../assets/scss/theme.scss';
|
@use '../assets/scss/theme.scss';
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export type MapMarkerGroup = "capitals" | "cities" | "towns" | "landmarks" | "quests" | "custom";
|
export type MapMarkerGroup = "capitals" | "cities" | "towns" | "landmarks" | "quests" | "custom";
|
||||||
|
export type MapMarkerIcon = "castle" | "flag" | "graduation-cap" | "location-pin" | "monument" | "push-pin"
|
||||||
|
|
||||||
export type MapCoords = {
|
export type MapCoords = {
|
||||||
x: number,
|
x: number,
|
||||||
@@ -11,6 +12,11 @@ export type MapMarker = {
|
|||||||
description?: string,
|
description?: string,
|
||||||
link?: string,
|
link?: string,
|
||||||
group?: MapMarkerGroup,
|
group?: MapMarkerGroup,
|
||||||
|
icon?: MapMarkerIcon,
|
||||||
|
cover?: string,
|
||||||
|
coverLink?: string,
|
||||||
|
coverAuthor?: string,
|
||||||
|
coverPortrait?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlayerMarker = {
|
export type PlayerMarker = {
|
||||||
|
|||||||