I have placed many custom overlays for different cities on a map and am trying to the hide/collapse the overlapping ones. Wherever there is space, I would like to show/expand the ones with the highest population.
I would like to achieve the exact same behavior as google flights (explore section).
What I tried
I have tried the following. I cycle through all custom overlays, check if there is overlap and then hide if there is one with higher population. The problem is that too many get hidden, see the following example:
- City A (3000 population)
- City B (2000 population)
- City C (1000 population)
- A and B overlap
- B and C overlap
- A and C do not overlap
Both A and C should be visible, but C is hidden because B and C overlap and B has a higher population.
Please note that I am using Angular, but this is a general js question.
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;
}
Does anyone know how to do this properly? I am also open to a completely different approach if the direction that I am heading is not efficient.
I found a solution. Not sure if it is the best way to do this, but it works.
I first create an array of objects with the overlay element, population and
hidden=false
. Then I cycle through and compare each element with all other elements. If the elements are overlapping andmain.hidden == true
andmain.population >= compare.population
, I set the compare element tohidden == true
. In this way the hidden elements do not cause other elements to hide.Note that my original array is already sorted by population, this order is important for this to work in the right way.
Finally I cycle through the elements again and add classes and styles to the elements based on if they are hidden or not.