From 740f13a2877c063040b688daca6b3c7db3ca349a Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 10 Jun 2013 22:27:17 +0100 Subject: [PATCH] minimap plugin - display a small map in the corner of the screen --- external/Control.MiniMap.css | 31 +++++ external/Control.MiniMap.js | 243 +++++++++++++++++++++++++++++++++++ images/minimap-toggle.png | Bin 0 -> 560 bytes plugins/minimap.user.js | 71 ++++++++++ 4 files changed, 345 insertions(+) create mode 100644 external/Control.MiniMap.css create mode 100644 external/Control.MiniMap.js create mode 100644 images/minimap-toggle.png create mode 100644 plugins/minimap.user.js diff --git a/external/Control.MiniMap.css b/external/Control.MiniMap.css new file mode 100644 index 00000000..c558467f --- /dev/null +++ b/external/Control.MiniMap.css @@ -0,0 +1,31 @@ +.leaflet-control-minimap { + border:solid rgba(255, 255, 255, 0.7) 3px; + box-shadow: 0 1px 7px #999; + background: #f8f8f9; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +.leaflet-control-minimap a { + background-color: rgba(255, 255, 255, 0.75); + background-position: 1px 2px; + background-repeat: no-repeat; + display: block; + outline: none; + z-index: 99999; +} + +.leaflet-control-minimap a.minimized { + background-position: 1px -18px; +} + +.leaflet-control-minimap-toggle-display { + background-image: url(@@INCLUDEIMAGE:images/minimap-toggle.png@@); + border-radius: 4px 4px 4px 4px; + height: 19px; + width: 19px; + position: absolute; + bottom: 0; + right: 0; +} diff --git a/external/Control.MiniMap.js b/external/Control.MiniMap.js new file mode 100644 index 00000000..db912307 --- /dev/null +++ b/external/Control.MiniMap.js @@ -0,0 +1,243 @@ +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); +}; diff --git a/images/minimap-toggle.png b/images/minimap-toggle.png new file mode 100644 index 0000000000000000000000000000000000000000..026d4c8bbc37882a9b685b7a685917b0651aadf2 GIT binary patch literal 560 zcmV-00?+-4P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*Y> z00=daXO&d|00FQ`L_t(Y$L-ZWOCv!T2Jm-XS&Pe_780^@R>Dg-F!&F<183lhkmkz! z0M}S62Zy}}#xD^37_tN*nY?0kSh*m?fyi~UOb`xstA%B3A{>&9yRpzBPdV`Z28MZN z0A`sg#u(cevruGaZroxJ1mC*d?zz_bL&io6xuD^2csLjgzWTm@8HVBVGh~g3&T>Ju zT8$jXfh0+`g%B4?spS!}N<Pacr#?8!U z9bTnUIZ{gf6GEKCas1i${Xc1%7CY>xc%IkfoRe+aFbR1PGRB}1T{%xXK!yN)%XA{GEFjcT+A05$-81b_$2vi|0RTCJAJ@HHZS zVT{Q_?SGaBMC9X;B2a{gb;j83RPWJKY}>x8R;zOAhi!yJX`1c`A+D5CpQeHk@n@sa z*esPw!#IxDd%fOu7>3)0AVfT7j5R&a8*t9QyRMr=QB-NS+g+{oPA&)$e>298{`&+3 y=lqA`I3`Jw`ydGJUUhr5*881KXJyvoH_jtgYr?XBn0V0u0000@@INCLUDESTRING:external/Control.MiniMap.css@@'); + + +}; + +var setup = window.plugin.miniMap.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script);