Google Maps Api V3 - скрыть перекрывающиеся пользовательские наложения
Я разместил на карте много пользовательских наложений для разных городов и пытаюсь скрыть / свернуть перекрывающиеся. Везде, где есть место, я хотел бы показать / расширить те, которые имеют наибольшее население.
Я хотел бы добиться того же поведения, что и рейсы Google (раздел изучения).
Что я пробовал
Я попробовал следующее. Я перебираю все пользовательские оверлеи, проверяю, есть ли перекрытия, а затем скрываю, есть ли с более высоким населением. Проблема в том, что слишком многие скрываются, см. Следующий пример:
- Город А (3000 жителей)
- Город Б (2000 жителей)
- Город С (1000 жителей)
- А и Б перекрываются
- B и C перекрываются
- А и С не перекрываются
И A, и C должны быть видны, но C скрыт, потому что B и C перекрываются, а B имеет более высокую популяцию.
Обратите внимание, что я использую Angular, но это общий вопрос JS.
hideOverlays(){
this.overlays.forEach(mainElement => {
let hide = false;
this.overlays.forEach(compareElement => {
if(this.checkOverlap(mainElement.nativeElement, compareElement.nativeElement)){
if(mainElement.nativeElement.dataset.population < compareElement.nativeElement.dataset.population){
hide = true
}
}
})
if(hide){
mainElement.nativeElement.style.display = "none";
}else{
mainElement.nativeElement.style.display = "flex";
}
});
}
checkOverlap(element1, element2) {
const rect1 = element1.getBoundingClientRect();
const rect2 = element2.getBoundingClientRect();
const overlap = !(rect1.right < rect2.left ||
rect1.left > rect2.right ||
rect1.bottom < rect2.top ||
rect1.top > rect2.bottom)
return overlap;
}
Кто-нибудь знает, как это сделать правильно? Я также открыт для совершенно другого подхода, если направление, которое я направляю, неэффективно.
1 ответ
Я нашел решение. Не уверен, что это лучший способ сделать это, но это работает.
Сначала я создаю массив объектов с наложенным элементом, населением и hidden=false
, Затем я перебираю и сравниваю каждый элемент со всеми другими элементами. Если элементы перекрываются и main.hidden == true
а также main.population >= compare.population
Я установил элемент сравнения на hidden == true
, Таким образом, скрытые элементы не вызывают скрытие других элементов.
Обратите внимание, что мой исходный массив уже отсортирован по населению, этот порядок важен для правильной работы.
Наконец, я снова перебираю элементы и добавляю классы и стили к элементам, основываясь на том, скрыты они или нет.
filterLocations(){
let overlayArray = [];
this.overlays.forEach(element => {
const overlayObj = {element: element.nativeElement, population: Number(element.nativeElement.dataset.population), hidden: false};
overlayArray.push(overlayObj);
})
overlayArray.forEach( (main, i) => {
overlayArray.forEach( (compare, j) => {
if(i != j && !main.hidden && main.population >= compare.population && this.checkOverlap(compare.element, main.element)){
overlayArray[j].hidden = true;
}
})
})
overlayArray.forEach( (obj, i) => {
if(!obj.hidden){
obj.element.classList.add("expanded");
obj.element.style.pointerEvents = 'auto';
obj.element.style.zIndex = overlayArray.length + overlayArray.length - i;
}else{
obj.element.classList.remove("expanded");
obj.element.style.pointerEvents = 'none';
obj.element.style.zIndex = overlayArray.length - i;
}
})
}
checkOverlap(element1, element2) {
const rect1 = element1.getBoundingClientRect();
const rect2 = element2.getBoundingClientRect();
return !(rect1.right < rect2.left ||
rect1.left > rect2.right ||
rect1.bottom < rect2.top ||
rect1.top > rect2.bottom)
}