Skip to content

Instantly share code, notes, and snippets.

@up209d
Last active November 29, 2017 07:02
Show Gist options
  • Save up209d/770753d2af9dadc6fb2b9c702fb39243 to your computer and use it in GitHub Desktop.
Save up209d/770753d2af9dadc6fb2b9c702fb39243 to your computer and use it in GitHub Desktop.
Leaflet Hack for Center Point with Offset X/Y (Top/Left)
// Change the center of map with offset value,
// useful for some cases such as
// a Menu/Sidebar sit on top of the map
// a Footer sit on top of the map
// This hack covers zoom/pan and tileLoading working correctly to the new center (with offset) point
(function(global){
global.Map.prototype._getNewPixelOrigin = function (center, zoom) {
var viewHalf = this.getSize()._divideBy(2);
if (this.options.offset) {
viewHalf.x += this.options.offset.x / 2;
viewHalf.y += this.options.offset.y / 2;
}
return this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();
};
global.Map.prototype._getCenterLayerPoint = function () {
var viewHalf = this.getSize()._divideBy(2);
if (this.options.offset) {
viewHalf.x += this.options.offset.x / 2;
viewHalf.y += this.options.offset.y / 2;
}
return this.containerPointToLayerPoint(viewHalf);
};
global.Map.prototype.setZoomAround = function (latlng, zoom, options) {
var scale = this.getZoomScale(zoom),
viewHalf = this.getSize().divideBy(2);
if (this.options.offset) {
viewHalf.x += this.options.offset.x / 2;
viewHalf.y += this.options.offset.y / 2;
}
var containerPoint = latlng instanceof global.Point ? latlng : this.latLngToContainerPoint(latlng);
var centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale);
var newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
return this.setView(newCenter, zoom, {zoom: options});
};
global.Map.prototype._limitCenter = function (center, zoom, bounds) {
if (!bounds) {
return center;
}
var centerPoint = this.project(center, zoom),
viewHalf = this.getSize().divideBy(2);
if (this.options.offset) {
viewHalf.x += this.options.offset.x / 2;
viewHalf.y += this.options.offset.y / 2;
}
var viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
offset = this._getBoundsOffset(viewBounds, bounds, zoom);
// If offset is less than a pixel, ignore.
// This prevents unstable projections from getting into
// an infinite loop of tiny offsets.
if (offset.round().equals([0, 0])) {
return center;
}
return this.unproject(centerPoint.add(offset), zoom);
};
global.Map.Drag.prototype._onZoomEnd = function () {
var pxCenter = this._map.getSize().divideBy(2);
if (this.options.offset) {
pxCenter.x += this.options.offset.x / 2;
pxCenter.y += this.options.offset.y / 2;
}
var pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
};
global.Map.prototype.shiftOffset = function (offset) {
this.options.offset.x = offset.x;
this.options.offset.y = offset.y;
this.invalidateSize();
};
global.GridLayer.prototype._getTiledPixelBounds = function (center) {
var map = this._map,
mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
scale = map.getZoomScale(mapZoom, this._tileZoom),
pixelCenter = map.project(center, this._tileZoom).floor(),
halfSize = map.getSize().divideBy(scale * 2);
if (map.options.offset) {
halfSize.x += map.options.offset.x / (scale * 2);
halfSize.y += map.options.offset.y / (scale * 2);
}
return new global.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
};
var any3d = !window.L_DISABLE_3D && (L.Browser.ie3d || L.Browser.webkit3d || L.Browser.gecko3d) && !L.Browser.opera12 && !L.Browser.phantom;
global.Renderer.prototype._updateTransform = function (center, zoom) {
var scale = this._map.getZoomScale(zoom, this._zoom);
var position = getPosition(this._container);
var viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding);
if (this._map.options.offset) {
viewHalf.x += this._map.options.offset.x*(0.5);
viewHalf.y += this._map.options.offset.y*(0.5);
}
var currentCenterPoint = this._map.project(this._center, zoom);
var destCenterPoint = this._map.project(center, zoom);
var centerOffset = destCenterPoint.subtract(currentCenterPoint);
var topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset);
if (any3d) {
setTransform(this._container, topLeftOffset, scale);
console.log('RENDERER: ',topLeftOffset)
} else {
setPosition(this._container, topLeftOffset);
}
};
function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance
return el._leaflet_pos || new Point(0, 0);
}
function setPosition(el, point) {
/*eslint-disable */
el._leaflet_pos = point;
/*eslint-enable */
if (any3d) {
setTransform(el, point);
} else {
el.style.left = point.x + 'px';
el.style.top = point.y + 'px';
}
}
var TRANSFORM = testProp(
['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
function setTransform(el, offset, scale) {
var pos = offset || new L.Point(0, 0);
el.style[TRANSFORM] =
(L.Browser.ie3d ?
'translate(' + pos.x + 'px,' + pos.y + 'px)' :
'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
(scale ? ' scale(' + scale + ')' : '');
}
function testProp(props) {
var style = document.documentElement.style;
for (var i = 0; i < props.length; i++) {
if (props[i] in style) {
return props[i];
}
}
return false;
}
})(L);
@up209d
Copy link
Author

up209d commented Nov 28, 2017

TO USE THE PLUGIN
Create Map with offset value in options

let anyMap = L.map('map_id_here', {
	offset: {
		x: 0, // Offset x Here
		y: 0 // Offset x Here
	}
}).setView([-39, 145], 6, {});

Create Map Tile as normal

let OpenStreetTile = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
	attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
	subdomains: 'abcd',
	minZoom: 6,
	maxZoom: 22
});

OpenStreetTile.addTo(anyMap);

Change to new Center offset

anyMap.shiftOffset({
	x: <New offsetX value>,
	y: <New offsetY value>
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment