Skip to content

Commit 8f70a57

Browse files
committed
feat: Add interactive map to navigate countries
1 parent 4b1f886 commit 8f70a57

File tree

12 files changed

+5953
-13
lines changed

12 files changed

+5953
-13
lines changed

assets/js/interactiveMap.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Panzoom from '@panzoom/panzoom';
2+
3+
window.initializeInteractiveMap = function() {
4+
const svg = document.querySelector('.o-interactive-map__container svg');
5+
if (svg) {
6+
// Ensure proper scaling
7+
svg.setAttribute('viewBox', '0 0 1300 1300');
8+
9+
const panzoom = Panzoom(svg, {
10+
maxScale: 5,
11+
minScale: 1,
12+
startScale: 1,
13+
contain: 'outside'
14+
});
15+
16+
// Enable mouse wheel zoom
17+
svg.parentElement.addEventListener('wheel', panzoom.zoomWithWheel);
18+
19+
// Enable double-click zoom
20+
svg.addEventListener('dblclick', (e) => {
21+
e.preventDefault();
22+
panzoom.zoomIn({ step: 0.5 });
23+
});
24+
25+
// Add country click functionality
26+
const countries = svg.querySelectorAll('[id]');
27+
countries.forEach(country => {
28+
if (window.availableCountries && window.availableCountries.includes(country.id)) {
29+
country.style.cursor = 'pointer';
30+
country.classList.add('o-interactive-map__country--available');
31+
32+
country.addEventListener('click', (e) => {
33+
e.stopPropagation();
34+
window.location.href = `/${window.currentLanguage}/country/${country.id}/`;
35+
});
36+
}
37+
});
38+
}
39+
};

assets/js/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ import './resizeObserver.js';
44
import './mediaqueries.js';
55
import './highlightHeadline.js';
66
import './anchorlinks.js';
7+
import './interactiveMap.js';

assets/sass/interactiveMap.scss

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.o-interactive-map {
2+
&__container {
3+
border-radius: var(--border-radius-m);
4+
box-shadow: var(--box-shadow);
5+
width: 100%;
6+
aspect-ratio: 1 / 1;
7+
8+
svg {
9+
width: 100%;
10+
height: 100%;
11+
}
12+
}
13+
14+
.o-interactive-map__country--available {
15+
path {
16+
fill: var(--link-default) !important;
17+
transition: all 0.2s ease;
18+
cursor: pointer;
19+
}
20+
21+
&:hover path {
22+
fill: var(--link-hovered) !important;
23+
}
24+
}
25+
26+
.o-interactive-map--loading {
27+
padding: 1rem;
28+
}
29+
}

assets/sass/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
@import "booking.scss";
1717
@import "button.scss";
1818
@import "startpage.scss";
19+
@import "interactiveMap.scss";

assets/sass/styles.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ img {
141141
align-items: center;
142142
}
143143

144+
.o-list__countries{
145+
display: grid;
146+
grid-template-columns: 1fr 1fr;
147+
gap: 1rem;
148+
149+
@media (max-width: #{$breakpoint-lg}) {
150+
display: flex;
151+
flex-direction: column;
152+
}
153+
}
154+
144155
@mixin add-columns($columns) {
145156
&--columns-#{$columns} {
146157
columns: $columns;

i18n/de.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ booking:
1414
reservation-costs: Reservierungskosten
1515
visit-additional-information-website: Weitere Informationen
1616
visit-booking-website: Zur Buchungsseite
17+
countries:
18+
overview: Alle Länder
19+
selection: Länderauswahl
1720
country:
1821
many: Länder
1922
one: Land
2023
other: Länder
21-
countryselection: Länderauswahl
2224
editPage: Seite bearbeiten
2325
footer-love:
2426
aria-label: Made with love in Frankfurt & Köln
@@ -32,6 +34,9 @@ home-page-text: FIP Guide Startseite
3234
information-disclaimer-short: >-
3335
Diese Informationen sind inoffiziell und ohne Gewähr. Es besteht keine
3436
rechtliche Verbindung zu FIP oder Bahngesellschaften.
37+
interactiveMap:
38+
loading: Lade interaktive Karte...
39+
title: Interaktive Länderkarte
3540
menu-close: Schließen
3641
menu-open: Menü
3742
navigate-to-country: Gehe zu Land

i18n/en.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ booking:
1313
reservation-costs: Reservation Costs
1414
visit-additional-information-website: Additional Information
1515
visit-booking-website: To Booking Website
16+
countries:
17+
overview: All Countries
18+
selection: choose country
1619
country:
1720
many: countries
1821
one: country
1922
other: countries
20-
countryselection: choose country
2123
editPage: Edit page
2224
footer-love:
2325
aria-label: Made with love in Frankfurt & Cologne
@@ -31,6 +33,9 @@ home-page-text: FIP Guide Home Page
3133
information-disclaimer-short: >-
3234
The information provided is unofficial and without guarantee. There is no
3335
legal connection to FIP or railway companies.
36+
interactiveMap:
37+
loading: Loading interactive map...
38+
title: Interactive Country Map
3439
menu-close: Close
3540
menu-open: Menu
3641
navigate-to-country: Navigate to country

layouts/country/list.html

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,52 @@
22
<article class="o-list o-list__container">
33
<h1 data-pagefind-meta="title">{{ .Title }}</h1>
44
{{ .Content }}
5-
<div class="o-list__list">
6-
{{ range .Pages }}
7-
<a href="{{ .RelPermalink }}" class="o-list__link">
8-
<div class="o-list__picture">
9-
{{ $object := replace .Path (printf "/%s/" .Page.Type) "" }}
10-
{{ partial "flag" $object }}
5+
6+
<div class="o-list__countries">
7+
<div>
8+
<h2>{{ T "countries.overview" }}</h2>
9+
<div class="o-list__list">
10+
{{ range .Pages }}
11+
<a href="{{ .RelPermalink }}" class="o-list__link">
12+
<div class="o-list__picture">
13+
{{ $object := replace .Path (printf "/%s/" .Page.Type) "" }}
14+
{{ partial "flag" $object }}
15+
</div>
16+
<div>
17+
{{ .Title }}
18+
</div>
19+
</a>
20+
{{ end }}
1121
</div>
12-
<div>
13-
{{ .Title }}
22+
</div>
23+
<div class="o-interactive-map">
24+
<h2>{{ T "interactiveMap.title" }}</h2>
25+
<div id="interactive-map__container" class="o-interactive-map__container">
26+
<p class="o-interactive-map--loading"><em>{{ T "interactiveMap.loading" }}</em></p>
1427
</div>
15-
</a>
16-
{{ end }}
28+
</div>
1729
</div>
1830
</article>
31+
32+
33+
<script>
34+
window.availableCountries = [
35+
{{- range .Pages -}}
36+
"{{ .File.ContentBaseName }}"{{ if not (eq . (index (last 1 $.Pages) 0)) }},{{ end }}
37+
{{- end -}}
38+
];
39+
40+
window.currentLanguage = "{{ .Language.Lang }}";
41+
42+
fetch('/map_europe.svg')
43+
.then(response => response.text())
44+
.then(svgContent => {
45+
document.getElementById('interactive-map__container').innerHTML = svgContent;
46+
47+
window.initializeInteractiveMap();
48+
})
49+
.catch(error => {
50+
console.error('Error loading SVG:', error);
51+
});
52+
</script>
1953
{{ end }}

layouts/partials/menu.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<menu>
2020
<li class="o-header__item">
2121
<button class="o-header__expand-button" aria-haspopup="true" aria-expanded="false">
22-
<span>{{ T "countryselection" }}</span>
22+
<span>{{ T "countries.selection" }}</span>
2323
{{ partial "icon" "keyboard_arrow_down" }}
2424
</button>
2525
<span id="menu-country-list-title">{{ T "country" }}</span>

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)