244 lines
6.9 KiB
JavaScript

L.Control.MiniMap = L.Control.extend({
options: {
position: 'bottomright',
toggleDisplay: false,
zoomLevelOffset: -5,
zoomLevelFixed: false,
zoomAnimation: false,
autoToggleDisplay: false,
width: 150,
height: 150
},
hideText: 'Hide MiniMap',
showText: 'Show MiniMap',
//layer is the map layer to be shown in the minimap
initialize: function (layer, options) {
L.Util.setOptions(this, options);
this._layer = layer;
},
onAdd: function (map) {
this._mainMap = map;
//Creating the container and stopping events from spilling through to the main map.
this._container = L.DomUtil.create('div', 'leaflet-control-minimap');
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
L.DomEvent.disableClickPropagation(this._container);
L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation);
this._miniMap = new L.Map(this._container,
{
attributionControl: false,
zoomControl: false,
zoomAnimation: this.options.zoomAnimation,
autoToggleDisplay: this.options.autoToggleDisplay,
touchZoom: !this.options.zoomLevelFixed,
scrollWheelZoom: !this.options.zoomLevelFixed,
doubleClickZoom: !this.options.zoomLevelFixed,
boxZoom: !this.options.zoomLevelFixed,
crs: map.options.crs
});
this._miniMap.addLayer(this._layer);
//These bools are used to prevent infinite loops of the two maps notifying each other that they've moved.
this._mainMapMoving = false;
this._miniMapMoving = false;
//Keep a record of this to prevent auto toggling when the user explicitly doesn't want it.
this._userToggledDisplay = false;
this._minimized = false;
if (this.options.toggleDisplay) {
this._addToggleButton();
}
this._miniMap.whenReady(L.Util.bind(function () {
this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap);
this._shadowRect = L.rectangle(this._mainMap.getBounds(), {color: "#000000", weight: 1, clickable: false,opacity:0,fillOpacity:0}).addTo(this._miniMap);
this._mainMap.on('moveend', this._onMainMapMoved, this);
this._mainMap.on('move', this._onMainMapMoving, this);
this._miniMap.on('movestart', this._onMiniMapMoveStarted, this);
this._miniMap.on('move', this._onMiniMapMoving, this);
this._miniMap.on('moveend', this._onMiniMapMoved, this);
}, this));
return this._container;
},
addTo: function (map) {
L.Control.prototype.addTo.call(this, map);
this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
this._setDisplay(this._decideMinimized());
return this;
},
onRemove: function (map) {
this._mainMap.off('moveend', this._onMainMapMoved, this);
this._mainMap.off('move', this._onMainMapMoving, this);
this._miniMap.off('moveend', this._onMiniMapMoved, this);
this._miniMap.removeLayer(this._layer);
},
_addToggleButton: function () {
this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
'', this.hideText, 'leaflet-control-minimap-toggle-display', this._container, this._toggleDisplayButtonClicked, this) : undefined;
},
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create('a', className, container);
link.innerHTML = html;
link.href = '#';
link.title = title;
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, 'click', stop)
.on(link, 'mousedown', stop)
.on(link, 'dblclick', stop)
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', fn, context);
return link;
},
_toggleDisplayButtonClicked: function () {
this._userToggledDisplay = true;
if (!this._minimized) {
this._minimize();
this._toggleDisplayButton.title = this.showText;
}
else {
this._restore();
this._toggleDisplayButton.title = this.hideText;
}
},
_setDisplay: function (minimize) {
if (minimize != this._minimized) {
if (!this._minimized) {
this._minimize();
}
else {
this._restore();
}
}
},
_minimize: function () {
// hide the minimap
if (this.options.toggleDisplay) {
this._container.style.width = '19px';
this._container.style.height = '19px';
this._toggleDisplayButton.className += ' minimized';
}
else {
this._container.style.display = 'none';
}
this._minimized = true;
},
_restore: function () {
if (this.options.toggleDisplay) {
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
this._toggleDisplayButton.className = this._toggleDisplayButton.className
.replace(/(?:^|\s)minimized(?!\S)/g, '');
}
else {
this._container.style.display = 'block';
}
this._minimized = false;
},
_onMainMapMoved: function (e) {
if (!this._miniMapMoving) {
this._mainMapMoving = true;
this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
this._setDisplay(this._decideMinimized());
} else {
this._miniMapMoving = false;
}
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMainMapMoving: function (e) {
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMiniMapMoveStarted:function (e) {
var lastAimingRect = this._aimingRect.getBounds();
var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest());
var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast());
this._lastAimingRectPosition = {sw:sw,ne:ne};
},
_onMiniMapMoving: function (e) {
if (!this._mainMapMoving && this._lastAimingRectPosition) {
this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne)));
this._shadowRect.setStyle({opacity:1,fillOpacity:0.3});
}
},
_onMiniMapMoved: function (e) {
if (!this._mainMapMoving) {
this._miniMapMoving = true;
this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false));
this._shadowRect.setStyle({opacity:0,fillOpacity:0});
} else {
this._mainMapMoving = false;
}
},
_decideZoom: function (fromMaintoMini) {
if (!this.options.zoomLevelFixed) {
if (fromMaintoMini)
return this._mainMap.getZoom() + this.options.zoomLevelOffset;
else
return this._miniMap.getZoom() - this.options.zoomLevelOffset;
} else {
if (fromMaintoMini)
return this.options.zoomLevelFixed;
else
return this._mainMap.getZoom();
}
},
_decideMinimized: function () {
if (this._userToggledDisplay) {
return this._minimized;
}
if (this.options.autoToggleDisplay) {
if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) {
return true;
}
return false;
}
return this._minimized;
}
});
L.Map.mergeOptions({
miniMapControl: false
});
L.Map.addInitHook(function () {
if (this.options.miniMapControl) {
this.miniMapControl = (new L.Control.MiniMap()).addTo(this);
}
});
L.control.minimap = function (options) {
return new L.Control.MiniMap(options);
};