Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add padding to google maps bounds.contains()

I have a sidebar which shows the names of the markers in the current map view of a google map. The sidebar contents change as the map gets moved:

google.maps.event.addListener(map, 'bounds_changed', function() {
            document.getElementById("list").innerHTML = "";
            var mklen = mkrs.length,
                a = 0,
                bnds = map.getBounds();

            for (a; a < mklen; a++) {
                var themk = mkrs[a];
                if (bnds.contains(themk.getPosition())) {
                    var myli = document.createElement("li");
                    myli.innerHTML = themk.title;
                    document.getElementById("list").appendChild(myli);
                }
            }
        });

That's working OK, but the thing is that the bounds.contains() is very strict - if just the bottom tip of the marker is on the map (ie, you can't see 99% of it) it gets listed on the sidebar. What I'd like is to have just the markers that are completely shown pass that test.

There are a couple of approaches that I can think of and I can't believe that nobody else has come up against this problem, so I'm wondering if there is a preference out of the following:

  1. take the bounds and recalculate them to be smaller than the actual bounds and use those new bounds for the bounds.contains() test
  2. calculate where the edges of the marker icons are (I guess using fromDivPixelToLatLng) then check that both the ne AND sw corners are within the bounds and if so, list the item

Before you ask, I haven't tried either of those - I'm more looking for advice on which would be best or even possible, or if there is another way to do this. Here's a fiddle demonstrating the issue, in case it clarifies

like image 466
lucas Avatar asked Nov 30 '22 16:11

lucas


1 Answers

In case anybody finds this later, I ended up recalculating the bounds - it seemed to be the approach that involved the least overhead. Here's the function:

function paddedBounds(npad, spad, epad, wpad) {
    var SW = map.getBounds().getSouthWest();
    var NE = map.getBounds().getNorthEast();
    var topRight = map.getProjection().fromLatLngToPoint(NE);
    var bottomLeft = map.getProjection().fromLatLngToPoint(SW);
    var scale = Math.pow(2, map.getZoom());

    var SWtopoint = map.getProjection().fromLatLngToPoint(SW);
    var SWpoint = new google.maps.Point(((SWtopoint.x - bottomLeft.x) * scale) + wpad, ((SWtopoint.y - topRight.y) * scale) - spad);
    var SWworld = new google.maps.Point(SWpoint.x / scale + bottomLeft.x, SWpoint.y / scale + topRight.y);
    var pt1 = map.getProjection().fromPointToLatLng(SWworld);

    var NEtopoint = map.getProjection().fromLatLngToPoint(NE);
    var NEpoint = new google.maps.Point(((NEtopoint.x - bottomLeft.x) * scale) - epad, ((NEtopoint.y - topRight.y) * scale) + npad);
    var NEworld = new google.maps.Point(NEpoint.x / scale + bottomLeft.x, NEpoint.y / scale + topRight.y);
    var pt2 = map.getProjection().fromPointToLatLng(NEworld);

    return new google.maps.LatLngBounds(pt1, pt2);
}

and you call it like this:

var padbnds = paddedBounds(50, 70, 100, 30);

specifying how much padding you want on the north, south, east and west edges of the map respectively

like image 96
lucas Avatar answered Dec 04 '22 12:12

lucas