Вопрос или проблема
Я пытаюсь создать кастомную карту. У меня есть изображение, и я хочу выбрать некоторые места и информацию. После добавления точек, когда я меняю размер окна, местоположение точек изменяется. Возможно ли сделать так, чтобы точки не меняли своё местоположение на изображении? Вот мой код:
<template>
<div class="px-20">
<div class="mt-10 shadow-2xl relative" ref="imageContainer">
<img :src="BL" class="w-full h-auto cursor-pointer" @click="addPoint" />
<div
v-for="(point, index) in points"
:key="index"
class="absolute"
:style="{
top: `${point.y}px`,
left: `${point.x}px`
}"
>
<div
class="bg-red-500 text-white text-xs font-semibold py-1 px-2 rounded-full flex items-center"
>
{{ point.label }}
<button
@click.stop="removePoint(index)"
class="bg-red-700 text-white text-xs font-bold rounded-full ml-1 w-4 h-4 flex items-center justify-center"
>
x
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import BL from '@/assets/Tm_Map.jpg' // Замените на путь к вашему изображению
const points = ref([])
let pointId = 0
const imageContainer = ref(null)
const resizeObserver = ref(null)
function addPoint(event) {
const rect = event.target.getBoundingClientRect()
const x = event.clientX - rect.left // Получаем x-позицию относительно изображения
const y = event.clientY - rect.top // Получаем y-позицию относительно изображения
points.value.push({
x,
y,
label: `Точка ${++pointId}`
})
}
function removePoint(index) {
points.value.splice(index, 1)
}
</script>
Если возможно, помогите мне!
Ответ или решение
Чтобы создать интерактивное изображение, подобное карте, с фиксированными точками, которые не изменяют свои позиции при изменении размера окна, нужно скорректировать вашу реализацию. Основная проблема состоит в том, что мы должны использовать относительные координаты для размещения точек, которые зависят от размеров родительского контейнера.
Мы можем добиться этого, используя процентные соотношения для координат, а не абсолютные пиксели. Вот шаги, как это реализовать:
Шаги по реализации
-
Измените хранение точек: Будем использовать относительные координаты для хранения положений точек на изображении.
-
Обновите обработчик добавления точек: Вместо сохранения координат в пикселях, производите вычисления для сохранения их в процентах относительно размеров изображения.
- Расчет позиции при рендеринге: При отображении точек передавайте относительные величины обратно в пиксели в соответствии с текущими размерами изображения.
Вот обновленный код вашего компонента:
Обновленный код
<template>
<div class="px-20">
<div class="mt-10 shadow-2xl relative" ref="imageContainer">
<img :src="BL" class="w-full h-auto cursor-pointer" @click="addPoint" />
<div
v-for="(point, index) in points"
:key="index"
class="absolute"
:style="{
top: `${point.y}%`,
left: `${point.x}%
}"
>
<div class="bg-red-500 text-white text-xs font-semibold py-1 px-2 rounded-full flex items-center">
{{ point.label }}
<button
@click.stop="removePoint(index)"
class="bg-red-700 text-white text-xs font-bold rounded-full ml-1 w-4 h-4 flex items-center justify-center"
>
x
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import BL from '@/assets/Tm_Map.jpg' // Замените на путь к вашему изображению
const points = ref([])
let pointId = 0
const imageContainer = ref(null)
function addPoint(event) {
const rect = event.target.getBoundingClientRect()
const x = ((event.clientX - rect.left) / rect.width) * 100 // Получаем x в процентах
const y = ((event.clientY - rect.top) / rect.height) * 100 // Получаем y в процентах
points.value.push({
x,
y,
label: `Point ${++pointId}`
})
}
function removePoint(index) {
points.value.splice(index, 1)
}
</script>
<style scoped>
.absolute {
position: absolute;
}
</style>
Объяснение изменений
-
Хранение точек: Теперь мы сохраняем координаты как проценты (
x
иy
). Это позволяет точкам сохранять свою позицию относительно размеров изображения, что делает их устойчивыми к изменениям размеров окна. -
Отображение: При рендеринге мы используем проценты для установки свойств
top
иleft
, тем самым гарантируя корректное отображение независимо от размера контейнера. - Стилизация: Применение
position: absolute;
для точек позволяет их позиционировать по заданным координатам.
Заключение
Теперь ваши точки будут фиксированы на изображении независимо от его размера, обеспечивая интерактивный опыт. Вы можете добавлять дополнительные стили и функциональность в зависимости от ваших требований.