Как получить маркеры или проверить их наличие в произвольном полигоне в библиотеке "vue-yandex-maps": "^2.0.0-rc.14"?
Опишу суть задачи. Мне нужно реализовать выделение какой-то области с помощью "лассо" на карте, и получить все маркеры в выделенной области(полигоне), с реализацией выделения области с помощью лассо я разобрался и теперь мне нужно каким то образом получить эти маркеры
Использую последнюю версию библиотеки vue-yandex-maps, поэтому используется API яндекс карт 3 версии, поэтому варианты по проверке наличия маркера в области полигона из 2 версий, не подойдут, я пытался...
Map.vue
<template>
<div class="map">
<MapTop
v-if="props.isSelectSeveral"
:drawButtonActive="drawButtonActive"
@drawButton="(status) => drawButton(status)"
/>
<div class="map__wrapper">
<YandexMap
v-model="map"
:settings="{
location: {
center: [37.54770, 55.643393],
zoom: 15,
}
}"
width="100%"
height="382px"
>
<YandexMapDefaultSchemeLayer />
<YandexMapDefaultFeaturesLayer />
<YandexMapMarker
v-for="(marker, index) in props.markers"
:key="index"
:settings="{
coordinates: marker.label.coords,
}"
>
<div class="marker"></div>
</YandexMapMarker>
<YandexMapControls :settings="{ position: 'left' }">
<YandexMapZoomControl :settings="{ easing: 'linear' }"/>
</YandexMapControls>
<YandexMapControls v-if="aloneItem && !props.isSelectSeveral" :settings="{ position: 'bottom right' }">
<YandexMapControlButton>
<a
:href="`https://maps.yandex.ru/?text=${aloneItem == null ? '55.755864+37.617698' : aloneItem.label.coords.join('+')}`"
target="_blank"
>
Открыть в Яндекс.Картах
</a>
</YandexMapControlButton>
</YandexMapControls>
<YandexMapFeature
v-model="polygon"
:settings="{
id: 'one',
geometry: {
type: 'Polygon',
coordinates: [polygonCoords],
},
style: {
fill: 'rgba(56, 56, 219, 0.5)',
stroke: [{ color: '#f00', width: 4 }],
}
}"
/>
</YandexMap>
<canvas
v-if="props.isSelectSeveral"
:style="drawButtonActive ? 'display: block' : 'display: none'"
class="map__canvas"
ref="mapCanvasRef"
/>
</div>
</div>
</template>
<script setup>
import './Map.scss'
import {
YandexMap,
YandexMapControlButton, YandexMapControls,
YandexMapDefaultFeaturesLayer,
YandexMapDefaultSchemeLayer, YandexMapFeature, YandexMapMarker, YandexMapZoomControl
} from "vue-yandex-maps";
import {computed, onMounted, ref, shallowRef, toRaw, watch} from "vue";
import MapTop from "@/components/AppMap/Map/MapTop/MapTop.vue";
const props = defineProps({
markers: {
default: [],
type: Array
},
isSelectSeveral: {
default: false,
type: Boolean
}
})
const aloneItem = computed(() => {
return props.markers.length === 1 ? props.markers[0] : null
})
const map = shallowRef(null)
const drawButtonActive = ref(false)
const canvasOptions = {
strokeStyle: '#0000ff',
lineWidth: 4,
opacity: 0.7
};
const polygon = ref(null)
const polygonCoords = ref([])
const tableDataCoords = ref([])
const mapCanvasRef = ref(null)
const dataSource = ref(null)
const drawButton = (status) => {
if (status) {
drawButtonActive.value = true
drawLineOverMap()
.then(function (coordinates) {
// Переводим координаты из 0..1 в географические.
coordinates = coordinates.map(function (x) {
return [
// Широта (latitude).
// Y переворачивается, т.к. на canvas'е он направлен вниз.
bounds[0][0] + x[0] * (bounds[1][0] - bounds[0][0]),
// Долгота (longitude).
bounds[0][1] + x[1] * (bounds[1][1] - bounds[0][1]),
];
});
// Тут надо симплифицировать линию.
coordinates = coordinates.filter(function (_, index) {
return index % 3 === 0;
});
// Удаляем старый полигон.
if (polygonCoords.value.length > 0) {
polygonCoords.value = []
}
polygonCoords.value = coordinates
drawButtonActive.value = false
});
} else {
drawButtonActive.value = false
}
}
const drawLineOverMap = () => {
const canvas = mapCanvasRef.value
const ctx2d = canvas.getContext('2d');
let drawing = false;
let coordinates = [];
// Задаем размеры канвасу как у карты.
const rect = map.value.container.getBoundingClientRect();
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
canvas.width = rect.width;
canvas.height = rect.height;
// Применяем стили.
ctx2d.strokeStyle = canvasOptions.strokeStyle;
ctx2d.lineWidth = canvasOptions.lineWidth;
canvas.style.opacity = canvasOptions.opacity;
ctx2d.clearRect(0, 0, canvas.width, canvas.height);
canvas.onmousedown = function (e) {
// При нажатии мыши запоминаем, что мы начали рисовать и координаты.
drawing = true;
coordinates.push([e.offsetX, e.offsetY]);
};
canvas.onmousemove = function (e) {
// При движении мыши запоминаем координаты и рисуем линию.
if (drawing) {
const last = coordinates[coordinates.length - 1];
ctx2d.beginPath();
ctx2d.moveTo(last[0], last[1]);
ctx2d.lineTo(e.offsetX, e.offsetY);
ctx2d.stroke();
coordinates.push([e.offsetX, e.offsetY]);
}
};
return new Promise(function (resolve) {
// При отпускании мыши запоминаем координаты и скрываем канвас.
canvas.onmouseup = function (e) {
coordinates.push([e.offsetX, e.offsetY]);
drawing = false;
coordinates = coordinates.map(function (x) {
return [x[0] / canvas.width, x[1] / canvas.height];
});
resolve(coordinates);
};
});
}
</script>
Ответы (1 шт):
Автор решения: Виктор Карев
→ Ссылка
В 3-й версии карт функции определения наличия маркера в полигоне отсутствует, поэтому приходится определять это самостоятельно.
function pointIsInPoly(p, polygon) {
var isInside = false;
var minX = polygon[0][0], maxX = polygon[0][0];
var minY = polygon[0][1], maxY = polygon[0][1];
for (var n = 1; n < polygon.length; n++) {
var q = polygon[n];
minX = Math.min(q[0], minX);
maxX = Math.max(q[0], maxX);
minY = Math.min(q[1], minY);
maxY = Math.max(q[1], maxY);
}
if (p[0] < minX || p[0] > maxX || p[1] < minY || p[1] > maxY) {
return false;
}
var i = 0, j = polygon.length - 1;
for (i, j; i < polygon.length; j = i++) {
if ((polygon[i][1] > p[1]) !== (polygon[j][1] > p[1]) &&
p[0] < (polygon[j][0] - polygon[i][0]) * (p[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0]) {
isInside = !isInside;
}
}
return isInside;
}
Пример использования, если полигонов несколько:
for (var i = 0; i < markers.length; i++) {
var point = markers[i].geometry.coordinates;
if (markers[i].found) {
var found = false;
for (var j = 0; j < polygons.length; j++) {
var polygon = polygons[j].geometry.coordinates[0]; // полигоны без дырок
if (pointIsInPoly(point, polygon)) {
found = true;
break;
}
}
if (!found) {
markers[i].found = false;
}
}
}