Skip to content

Commit

Permalink
Frontend: Add map and IIIF viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
bierik committed Sep 7, 2024
1 parent 7741943 commit b9b5ceb
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 10 deletions.
1 change: 1 addition & 0 deletions api/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.env
/var/
/venv/
/**/__pycache__
Empty file.
5 changes: 5 additions & 0 deletions frontend/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export default defineNuxtConfig({
},
nitro: {
preset: "static",
devProxy: {
"/api/": {
target: `http://localhost:8000/api/`,
},
},
},
compatibilityDate: "2024-09-06",
});
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"dependencies": {
"@vueuse/core": "^11.0.3",
"leaflet": "^1.9.4",
"lodash-es": "^4.17.21"
"lodash-es": "^4.17.21",
"tify": "^0.31.0"
},
"packageManager": "[email protected]+sha512.60c18acd138bff695d339be6ad13f7e936eea6745660d4cc4a776d5247c540d0edee1a563695c183a66eb917ef88f2b4feb1fc25f32a7adcadc7aaf3438e99c1"
}
37 changes: 37 additions & 0 deletions frontend/pages/iiif.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<template>
<div id="iiif-viewer" class="h-screen w-screen" />
</template>
<script setup>
import "tify";
import "tify/dist/tify.css";
import { isNull } from "lodash-es";
const tify = ref(null);
const route = useRoute();
function constructManifestURL(imageURL) {
return imageURL.replace(/\/files\/.*/, "/pages/1/manifest/");
}
function openViewer() {
tify.value = new window.Tify({
container: "#iiif-viewer",
manifestUrl: constructManifestURL(route.query.manifestURL),
});
}
function destroyViewer() {
if (isNull(toValue(tify))) {
return;
}
toValue(tify).destroy();
}
onMounted(() => {
openViewer();
});
onBeforeUnmount(() => {
destroyViewer();
});
</script>
104 changes: 102 additions & 2 deletions frontend/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,104 @@
<template>
<h1></h1>
<div
v-for="(radarPoint, index) in radarPoints"
:key="index"
class="absolute size-4 origin-center rounded-full bg-blue-400"
:style="radarPoint"
style="z-index: 9999"
/>
<div id="map" class="h-screen w-screen" />
</template>
<script setup></script>
<script setup>
import { map as lodashMap } from "lodash-es";
import {
useGeolocation,
useDeviceOrientation,
useWindowSize,
} from "@vueuse/core";
import { computed, toValue } from "vue";
import "leaflet/dist/leaflet.css";
import L from "leaflet";
const { coords } = useGeolocation();
const { alpha } = useDeviceOrientation();
const { data } = useFetchPhotos(coords, 1000);
const { width, height } = useWindowSize();
const router = useRouter();
const orientation = computed(() => toValue(alpha) * (Math.PI / 180));
const windowCenter = computed(() => ({
x: toValue(width) / 2,
y: toValue(height) / 2,
}));
const radius = computed(() => toValue(width) / 2 - 16);
const pointsInProximity = computed(() =>
lodashMap(toValue(data), "coordinates"),
);
const radarPoints = computed(() => {
return toValue(pointsInProximity).map((point) => {
const beta = Math.tanh(
(point.lat - toValue(coords).latitude) /
(point.lon - toValue(coords).longitude),
);
const tangentPoint = {
x:
toValue(windowCenter).x +
toValue(radius) *
Math.cos(toValue(beta) + toValue(orientation) - Math.PI / 2),
y:
toValue(windowCenter).y +
toValue(radius) *
Math.sin(toValue(beta) + toValue(orientation) - Math.PI / 2),
};
return {
transform: `translate(${tangentPoint.x - 16}px, ${tangentPoint.y - 16}px)`,
};
});
});
const initialZoom = 20;
const layer = {
url: "https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg",
attribution: "© swisstopo",
};
let map = null;
const me = L.marker();
const photosLayer = L.layerGroup();
onMounted(() => {
map = L.map("map", { zoomControl: false });
L.tileLayer(layer.url, { attribution: layer.attribution }).addTo(map);
photosLayer.addTo(map);
me.addTo(map);
});
watch(coords, ({ latitude, longitude }) => {
me.setLatLng([latitude, longitude]);
map.setView(new L.LatLng(latitude, longitude), initialZoom);
});
function placePhotos(photos) {
photosLayer.clearLayers();
photos.forEach(({ coordinates: { lat, lon }, image_url, iiif_url }) => {
const marker = L.marker([lat, lon]).bindPopup(
`<img src="${image_url}" />`,
{
maxWidth: 200,
minWidth: 200,
maxHeight: 200,
minHeight: 200,
},
);
marker.on("popupopen", function () {
const popupContent = document.querySelector(".leaflet-popup-content");
popupContent.addEventListener("click", () => {
router.push({ name: "iiif", query: { manifestURL: iiif_url } });
});
});
marker.addTo(photosLayer);
});
}
watch(data, placePhotos);
</script>
33 changes: 26 additions & 7 deletions frontend/pages/map/index.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
<template>
<div id="map" class="h-screen w-screen"></div>
<div id="map" class="h-screen w-screen" />
</template>
<script setup>
import "leaflet/dist/leaflet.css";
import L from "leaflet";
import { useGeolocation } from "@vueuse/core";
const { coords } = useGeolocation();
const router = useRouter();
const initialPosition = [46.801111, 8.226667];
const initialZoom = 20;
const layer = {
url: "https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg",
attribution: "© swisstopo",
};
let map = null;
const me = L.marker(initialPosition);
const { data } = useFetchPhotos(coords, 0);
const me = L.marker();
const { data } = useFetchPhotos(coords, 1000);
const photosLayer = L.layerGroup();
onMounted(() => {
map = L.map("map", { zoomControl: false });
map = L.map("map", { zoomControl: false, dragging: false, tap: false });
map.dragging.disable();
L.tileLayer(layer.url, { attribution: layer.attribution }).addTo(map);
photosLayer.addTo(map);
me.addTo(map);
});
Expand All @@ -31,8 +34,24 @@ watch(coords, ({ latitude, longitude }) => {
});
function placePhotos(photos) {
photos.forEach(({ coordinates: { coordinates } }) => {
L.marker(coordinates).addTo(map);
photosLayer.clearLayers();
photos.forEach(({ coordinates: { lat, lon }, image_url, iiif_url }) => {
const marker = L.marker([lat, lon]).bindPopup(
`<img src="${image_url}" />`,
{
maxWidth: 200,
minWidth: 200,
maxHeight: 200,
minHeight: 200,
},
);
marker.on("popupopen", function () {
const popupContent = document.querySelector(".leaflet-popup-content");
popupContent.addEventListener("click", () => {
router.push({ name: "iiif", query: { manifestURL: iiif_url } });
});
});
marker.addTo(photosLayer);
});
}
watch(data, placePhotos);
Expand Down
9 changes: 9 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b9b5ceb

Please sign in to comment.