Google Maps Api V3 - скрыть перекрывающиеся пользовательские наложения - PullRequest
0 голосов
/ 05 февраля 2019

Я поместил много пользовательских наложений для разных городов на карту и пытаюсь скрыть / свернуть перекрывающиеся.Везде, где есть место, я хотел бы показать / развернуть те из них с наибольшим населением.

Я бы хотел добиться того же поведения, что и полеты Google (раздел изучения) .

Что я пробовал

Я пробовал следующее.Я перебираю все пользовательские оверлеи, проверяю, есть ли перекрытия, а затем скрываю, есть ли с более высоким населением.Проблема в том, что слишком многие скрываются, см. Следующий пример:

  • Город A (3000 человек)
  • Город B (2000 человек)
  • Город C (1000 населения)
  • A и B перекрываются
  • B и C перекрываются
  • A и 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 Ответ

0 голосов
/ 05 февраля 2019

Я нашел решение.Не уверен, что это лучший способ сделать это, но он работает.

Сначала я создаю массив объектов с наложенным элементом, населением и 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)
}
...