Add an option to make the map's maxBounds non-bouncy. Fixes #1673.

This commit is contained in:
Iván Sánchez Ortega 2015-06-02 15:42:50 +02:00
parent bd1b88c1dd
commit 8a352fbbbf
3 changed files with 88 additions and 3 deletions

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>Leaflet debug page</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="../../dist/leaflet.css" />
<link rel="stylesheet" href="../css/mobile.css" />
<script type="text/javascript" src="../../build/deps.js"></script>
<script src="../leaflet-include.js"></script>
</head>
<body>
<h1>Left: Bouncy maxBounds. Right: Not bouncy.</h1>
<div id="map1" style="float: left; width:45%; height: 80%;"></div>
<div id="map2" style="float: left; width:45%; height: 80%;"></div>
<script type="text/javascript">
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
osm1 = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}),
osm2 = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}),
bounds = new L.LatLngBounds(new L.LatLng(49.5, -11.3), new L.LatLng(61.2, 2.5));
var map1 = new L.Map('map1', {
center: bounds.getCenter(),
zoom: 5,
layers: [osm1],
maxBounds: bounds,
maxBoundsViscosity: 0.75
});
var map2 = new L.Map('map2', {
center: bounds.getCenter(),
zoom: 5,
layers: [osm2],
maxBounds: bounds,
maxBoundsViscosity: 1.0
});
var latlngs = L.rectangle(bounds).getLatLngs();
L.polyline(latlngs.concat([latlngs[0]])).addTo(map1);
L.polyline(latlngs.concat([latlngs[0]])).addTo(map2);
</script>
</body>
</html>

View File

@ -15,7 +15,8 @@ L.Map = L.Evented.extend({
fadeAnimation: true, fadeAnimation: true,
trackResize: true, trackResize: true,
markerZoomAnimation: true markerZoomAnimation: true,
maxBoundsViscosity: 0.0
}, },
initialize: function (id, options) { // (HTMLElement or String, Object) initialize: function (id, options) { // (HTMLElement or String, Object)

View File

@ -28,8 +28,9 @@ L.Map.Drag = L.Handler.extend({
dragend: this._onDragEnd dragend: this._onDragEnd
}, this); }, this);
this._draggable.on('predrag', this._onPreDragLimit, this);
if (map.options.worldCopyJump) { if (map.options.worldCopyJump) {
this._draggable.on('predrag', this._onPreDrag, this); this._draggable.on('predrag', this._onPreDragWrap, this);
map.on('viewreset', this._onViewReset, this); map.on('viewreset', this._onViewReset, this);
map.whenReady(this._onViewReset, this); map.whenReady(this._onViewReset, this);
@ -55,6 +56,19 @@ L.Map.Drag = L.Handler.extend({
_onDragStart: function () { _onDragStart: function () {
var map = this._map; var map = this._map;
if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
var bounds = L.latLngBounds(this._map.options.maxBounds);
this._offsetLimit = L.bounds(
this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)
.add(this._map.getSize()));
this._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));
} else {
this._offsetLimit = null;
}
map map
.fire('movestart') .fire('movestart')
.fire('dragstart'); .fire('dragstart');
@ -92,7 +106,25 @@ L.Map.Drag = L.Handler.extend({
this._worldWidth = this._map.getPixelWorldBounds().getSize().x; this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
}, },
_onPreDrag: function () { _viscousLimit: function(value, threshold) {
return value - (value - threshold) * this._viscosity;
},
_onPreDragLimit: function () {
if (!this._viscosity || !this._offsetLimit) { return; }
var offset = this._draggable._newPos.subtract(this._draggable._startPos);
var limit = this._offsetLimit;
if (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }
if (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }
if (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }
if (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }
this._draggable._newPos = this._draggable._startPos.add(offset);
},
_onPreDragWrap: function () {
// TODO refactor to be able to adjust map pane position after zoom // TODO refactor to be able to adjust map pane position after zoom
var worldWidth = this._worldWidth, var worldWidth = this._worldWidth,
halfWidth = Math.round(worldWidth / 2), halfWidth = Math.round(worldWidth / 2),