кластеризация
Gitea Actions Demo / build_and_push (push) Successful in 52s Details

This commit is contained in:
artem 2026-09-17 15:00:38 +03:00
parent 9c8e6f6308
commit 76b93dbadc
1 changed files with 71 additions and 14 deletions

View File

@ -70,6 +70,7 @@
color: 'gray', color: 'gray',
}" }"
/> />
<yandex-map-clusterer :grid-size="64" zoom-on-cluster-click>
<yandex-map-marker <yandex-map-marker
v-for="photo in photosWithCoords" v-for="photo in photosWithCoords"
:key="'photo-' + photo.id" :key="'photo-' + photo.id"
@ -84,6 +85,10 @@
> >
<img :src="photo.url" class="map-photo-marker" :alt="photo.id" /> <img :src="photo.url" class="map-photo-marker" :alt="photo.id" />
</yandex-map-marker> </yandex-map-marker>
<template #cluster="{ length }">
<div class="photo-cluster">{{ length }}</div>
</template>
</yandex-map-clusterer>
</yandex-map> </yandex-map>
</div> </div>
<div id="workout-short-data"> <div id="workout-short-data">
@ -223,6 +228,22 @@
<div class="workout-photos-grid" v-if="photos.length > 0"> <div class="workout-photos-grid" v-if="photos.length > 0">
<div class="workout-photo" v-for="photo in photos" :key="photo.id"> <div class="workout-photo" v-for="photo in photos" :key="photo.id">
<img :src="photo.url" :alt="photo.id" @click="openPhoto(photo)" /> <img :src="photo.url" :alt="photo.id" @click="openPhoto(photo)" />
<svg
v-if="photo.latitude !== null && photo.longitude !== null"
class="workout-photo-loc"
viewBox="0 0 24 24"
width="16"
height="16"
@click.stop="focusPhotoOnMap(photo)"
>
<path
d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z"
fill="#fff"
stroke="#000"
stroke-width="1"
/>
<circle cx="12" cy="9" r="2.5" fill="#007afc" />
</svg>
<VaButton <VaButton
v-if="isPrivate" v-if="isPrivate"
preset="danger" preset="danger"
@ -434,6 +455,7 @@ import {
YandexMapDefaultMarker, YandexMapDefaultMarker,
YandexMapMarker, YandexMapMarker,
YandexMapListener, YandexMapListener,
YandexMapClusterer,
} from "vue-yandex-maps"; } from "vue-yandex-maps";
import { import {
WorkoutItem, WorkoutItem,
@ -1182,6 +1204,15 @@ const openPhoto = (photo: WorkoutPhoto) => {
showLightbox.value = true; showLightbox.value = true;
} }
}; };
function focusPhotoOnMap(photo: WorkoutPhoto) {
if (photo.latitude === null || photo.longitude === null) return;
map.value?.update({
location: {
center: [photo.longitude as number, photo.latitude as number] as LngLat,
zoom: 15,
},
});
}
const prevPhoto = () => { const prevPhoto = () => {
lightboxIndex.value = lightboxIndex.value =
(lightboxIndex.value - 1 + photos.value.length) % photos.value.length; (lightboxIndex.value - 1 + photos.value.length) % photos.value.length;
@ -1454,6 +1485,32 @@ h3 {
cursor: pointer; cursor: pointer;
display: block; display: block;
} }
.photo-cluster {
width: 40px;
height: 40px;
border-radius: 50%;
background: #007afc;
color: #fff;
font-weight: 600;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
cursor: pointer;
}
.workout-photo-loc {
position: absolute;
bottom: 4px;
right: 4px;
background: rgba(0, 0, 0, 0.45);
border-radius: 50%;
padding: 2px;
cursor: pointer;
z-index: 2;
color: #fff;
}
.photo-lightbox { .photo-lightbox {
position: fixed; position: fixed;
inset: 0; inset: 0;