user142951
user142951

Reputation:

How does one specify an "active" region of a leaflet map?

Please consider: http://jsfiddle.net/msNs5/3/

I have a map div that expands to full size on page load, and another semi-transparent div that covers the bottom of it. Aesthetically, I really like how the bottom div looks with the map behind it, but I need to make it so that the region that isn't covered by the transparent div is the "active" region.

I.E. when the map calculates bounds for markers and polygons and sets it's view, it calcualtes to that exposed region instead of the whole map itself. People seem to think this is possible but I'm struggling with the actual implementation.

Code from the fiddle is below:

// JavaScript
var map = L.map('map', { center: [51.505, -0.09], zoom: 13 });
osm = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {});
map.addLayer(osm);

function initMap() {
  $('#map').css({"height": $(window).height() + "px"});
  map.setView(map.getCenter(),map.getZoom());
}

var id;
$(window).resize(function() {
  clearTimeout(id);

  id = setTimeout(initMap, 500);
});

$('#map').css({"height": $(window).height() + "px"});
  map.setView(map.getCenter(),map.getZoom());

/* CSS */
#map { position: fixed; z-index: -1; width: 100%; }
#header { height: 40px; background: black; }
#otherstuff { position: fixed; bottom: 0px; width: 100%; background-color: rgba(255,255,255,0.6); height: 30%; }

<!-- HTML --->
<!DOCTYPE html>
<body>
    <div id="header"></div>
    <div id="map"></div>

    <div id="otherstuff">xxx</div>
</body>

Upvotes: 2

Views: 1209

Answers (1)

user142951
user142951

Reputation:

Thanks to @mourner on the #leaflet channel, I was directed to this Github issues thread, and this comment in particular:

https://github.com/Leaflet/Leaflet/issues/859#issuecomment-11436202

It defines a mixin for offsetting the map center:

MapCenterOffsetMixin = {
    UIOffset: [550, 0], // x, y
    getBounds: function(){
        var a=this.getPixelBounds(),
            b=this.unproject(new L.Point(a.min.x+this.UIOffset[0],a.max.y+this.UIOffset[1]), this._zoom,!0),
            c=this.unproject(new L.Point(a.max.x,a.min.y),this._zoom,!0);
            return new L.LatLngBounds(b,c)
    },
    _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) {
        var targetPoint = this.project(newCenter, newCenter).subtract([this.UIOffset[0]/2, this.UIOffset[1]/2]),
            newCenter = this.unproject(targetPoint, newZoom);
        var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos());
        return this.project(latlng, newZoom)._subtract(topLeft);
    },
    _getCenterLayerPoint: function () {
        return this.containerPointToLayerPoint(this.getSize().divideBy(2).add([this.UIOffset[0]/2, this.UIOffset[1]/2]));
    },
    _resetView: function (a, b, c, d) {
        var e = this._zoom !== b;
        // Change the center
        var targetPoint = this.project(a, b).subtract([this.UIOffset[0] / 2, this.UIOffset[1]/2]),
            a = this.unproject(targetPoint, b);
        d || (this.fire("movestart"), e && this.fire("zoomstart")), this._zoom = b, this._initialTopLeftPoint = this._getNewTopLeftPoint(a);
        if (!c) L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
        else {
            var f = L.DomUtil.getPosition(this._mapPane);
            this._initialTopLeftPoint._add(f)
        }
        this._tileLayersToLoad = this._tileLayersNum, this.fire("viewreset", {
            hard: !c
        }), this.fire("move"), (e || d) && this.fire("zoomend"), this.fire("moveend"), this._loaded || (this._loaded = !0, this.fire("load"))
    }
}

L.Map.include(MapCenterOffsetMixin);

This worked very well for me.

Upvotes: 2

Related Questions