(map) add bidirectional interactivity between map and links

This commit is contained in:
Valentyne Stigloher 2024-05-30 14:58:58 +02:00
parent 2f0f482b46
commit 19c427f9d1
2 changed files with 45 additions and 10 deletions

View File

@ -9,6 +9,7 @@
<script lang="ts"> <script lang="ts">
import type { PropType } from 'vue';
import dark from '../plugins/dark.ts'; import dark from '../plugins/dark.ts';
import walsLanguages from '~/assets/languages.csv'; import walsLanguages from '~/assets/languages.csv';
import polygonsByLocale from '~/assets/map.json'; import polygonsByLocale from '~/assets/map.json';
@ -37,11 +38,23 @@ declare module 'leaflet' {
} }
export default dark.extend({ export default dark.extend({
props: {
highlightedLocale: { default: null, type: String as PropType<string | null> },
},
data() { data() {
return { return {
polygons: {} as Record<string, L.Polygon[]>, polygons: {} as Record<string, L.Polygon[]>,
}; };
}, },
watch: {
highlightedLocale() {
for (const [locale, polygons] of Object.entries(this.polygons)) {
for (const polygon of polygons) {
polygon.setStyle({ fillOpacity: locale === this.highlightedLocale ? 1 : 0.2 });
}
}
},
},
async mounted() { async mounted() {
const { default: L } = await import('leaflet'); const { default: L } = await import('leaflet');
await import ('@elfalem/leaflet-curve'); await import ('@elfalem/leaflet-curve');
@ -129,10 +142,10 @@ export default dark.extend({
}).addTo(map); }).addTo(map);
circle.bindTooltip(`<strong>${locale.name}</strong><br/>${clearUrl(locale.url)}`, { opacity: 1 }); circle.bindTooltip(`<strong>${locale.name}</strong><br/>${clearUrl(locale.url)}`, { opacity: 1 });
circle.on('mouseover', () => { circle.on('mouseover', () => {
this.polygons[locale.code].map((polygon) => polygon.setStyle({ fillOpacity: 1 })); this.$emit('update', locale.code);
}); });
circle.on('mouseout', () => { circle.on('mouseout', () => {
this.polygons[locale.code].map((polygon) => polygon.setStyle({ fillOpacity: 0.2 })); this.$emit('update', null);
}); });
circle.on('click', () => { circle.on('click', () => {
window.open(locale.url); window.open(locale.url);

View File

@ -1,7 +1,24 @@
<template> <template>
<Page> <Page>
<div class="list-group d-flex flex-wrap flex-row my-4">
<a
v-for="(options, locale) in $locales"
:key="locale"
:href="options.url"
:class="['list-group-item', 'list-group-item-action', locale === highlightedLocale ? 'list-group-item-highlighted' : '', 'w-md-50']"
@mouseenter="highlightedLocale = locale"
@mouseleave="highlightedLocale = null"
>
<div class="h3">
<LocaleIcon :locale="options" class="mx-2" />
{{ options.name }}
<small v-if="options.extra" class="text-muted">({{ options.extra }})</small>
</div>
</a>
</div>
<template #below> <template #below>
<LanguageMap /> <!-- @vue-ignore -->
<LanguageMap :highlighted-locale="highlightedLocale" @update="(locale) => highlightedLocale = locale" />
<p class="small text-muted my-3"> <p class="small text-muted my-3">
<Icon v="info-circle" /> <Icon v="info-circle" />
The complexity of geographical reach of each language is represented in a simplified way The complexity of geographical reach of each language is represented in a simplified way
@ -11,17 +28,22 @@
</template> </template>
</Page> </Page>
</template> </template>
<script lang="ts">
import Vue from 'vue';
<script setup lang="ts"> export default Vue.extend({
data() {
return {
highlightedLocale: null as string | null,
};
},
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "assets/variables"; @import "assets/variables";
.list-group-item-hoverable { .list-group-item-highlighted {
&:hover { border-left: 3px solid $primary !important;
color: $primary;
border-inline-start: 3px solid $primary;
padding-inline-start: calc(#{$list-group-item-padding-x} - 2px); padding-inline-start: calc(#{$list-group-item-padding-x} - 2px);
} }
}
</style> </style>