-L.Control.Zoomslider = L.Control.extend({\r
- options: {\r
- position: 'topleft',\r
- // height in px of zoom-slider.png\r
- stepHeight: 9\r
- },\r
-\r
- onAdd: function (map) {\r
- var className = 'leaflet-control-zoomslider',\r
- container = L.DomUtil.create('div', className);\r
-\r
- L.DomEvent\r
- .on(container, 'click', L.DomEvent.stopPropagation)\r
- .on(container, 'mousedown', L.DomEvent.stopPropagation)\r
- .on(container, 'dblclick', L.DomEvent.stopPropagation);\r
- \r
- this._map = map;\r
-\r
- this._zoomInButton = this._createButton('+', 'Zoom in', className + '-in'\r
- , container, this._zoomIn , this);\r
- this._createSlider(className + '-slider', container, map);\r
- this._zoomOutButton = this._createButton('-', 'Zoom out', className + '-out'\r
- , container, this._zoomOut, this);\r
- \r
- map.on('layeradd layerremove', this._refresh, this);\r
-\r
- map.whenReady(function(){\r
- this._snapToSliderValue();\r
- map.on('zoomend', this._snapToSliderValue, this);\r
- }, this);\r
-\r
- return container;\r
- },\r
-\r
- onRemove: function(map){\r
- map.off('zoomend', this._snapToSliderValue);\r
- map.off('layeradd layerremove', this._refresh);\r
- },\r
-\r
- _refresh: function(){\r
- this._map\r
- .removeControl(this)\r
- .addControl(this);\r
- },\r
-\r
- _createSlider: function (className, container, map) {\r
- var zoomLevels = map.getMaxZoom() - map.getMinZoom();\r
- this._sliderHeight = this.options.stepHeight * zoomLevels;\r
-\r
- var wrapper = L.DomUtil.create('div', className + '-wrap', container);\r
- wrapper.style.height = (this._sliderHeight + 5) + "px";\r
- var slider = L.DomUtil.create('div', className, wrapper);\r
- this._knob = L.DomUtil.create('div', className + '-knob', slider);\r
-\r
- this._draggable = this._createDraggable();\r
- this._draggable.enable();\r
-\r
- L.DomEvent.on(slider, 'click', this._onSliderClick, this);\r
-\r
- return slider;\r
- },\r
-\r
- _zoomIn: function (e) {\r
- this._map.zoomIn(e.shiftKey ? 3 : 1);\r
- },\r
-\r
- _zoomOut: function (e) {\r
- this._map.zoomOut(e.shiftKey ? 3 : 1);\r
- },\r
-\r
- _createButton: function (html, title, className, container, fn, context) {\r
- var link = L.DomUtil.create('a', className, container);\r
- link.innerHTML = html;\r
- link.href = '#';\r
- link.title = title;\r
-\r
- L.DomEvent\r
- .on(link, 'click', L.DomEvent.preventDefault)\r
- .on(link, 'click', fn, context);\r
-\r
- return link;\r
- },\r
-\r
- _createDraggable: function() {\r
- L.DomUtil.setPosition(this._knob, new L.Point(0, 0));\r
- L.DomEvent\r
- .on(this._knob\r
- , L.Draggable.START\r
- , L.DomEvent.stopPropagation)\r
- .on(this._knob, 'click', L.DomEvent.stopPropagation);\r
-\r
- var bounds = new L.Bounds(\r
- new L.Point(0, 0),\r
- new L.Point(0, this._sliderHeight)\r
- );\r
- var draggable = new L.BoundedDraggable(this._knob,\r
- this._knob,\r
- bounds)\r
- .on('drag', this._snap, this)\r
- .on('dragend', this._setZoom, this);\r
-\r
- return draggable;\r
- },\r
-\r
- _snap : function(){\r
- this._snapToSliderValue(this._posToSliderValue());\r
- },\r
- _setZoom: function() {\r
- this._map.setZoom(this._toZoomLevel(this._posToSliderValue()));\r
- },\r
-\r
- _onSliderClick: function(e){\r
- var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e);\r
- var offset = first.offsetY\r
- ? first.offsetY\r
- : L.DomEvent.getMousePosition(first).y\r
- - L.DomUtil.getViewportOffset(this._knob).y;\r
- var value = this._posToSliderValue(offset - this._knob.offsetHeight / 2);\r
- this._snapToSliderValue(value);\r
- this._map.setZoom(this._toZoomLevel(value));\r
- },\r
-\r
- _posToSliderValue: function(pos) {\r
- pos = isNaN(pos)\r
- ? L.DomUtil.getPosition(this._knob).y\r
- : pos;\r
- return Math.round( (this._sliderHeight - pos) / this.options.stepHeight);\r
- },\r
-\r
- _snapToSliderValue: function(sliderValue) {\r
- this._updateDisabled();\r
- if(this._knob) {\r
- sliderValue = isNaN(sliderValue)\r
- ? this._getSliderValue()\r
- : sliderValue;\r
- var y = this._sliderHeight\r
- - (sliderValue * this.options.stepHeight);\r
- L.DomUtil.setPosition(this._knob, new L.Point(0, y));\r
- }\r
- },\r
- _toZoomLevel: function(sliderValue) {\r
- return sliderValue + this._map.getMinZoom();\r
- },\r
- _toSliderValue: function(zoomLevel) {\r
- return zoomLevel - this._map.getMinZoom();\r
- },\r
- _getSliderValue: function(){\r
- return this._toSliderValue(this._map.getZoom());\r
- },\r
-\r
- _updateDisabled: function () {\r
- var map = this._map,\r
- className = 'leaflet-control-zoomslider-disabled';\r
-\r
- L.DomUtil.removeClass(this._zoomInButton, className);\r
- L.DomUtil.removeClass(this._zoomOutButton, className);\r
-\r
- if (map.getZoom() === map.getMinZoom()) {\r
- L.DomUtil.addClass(this._zoomOutButton, className);\r
- }\r
- if (map.getZoom() === map.getMaxZoom()) {\r
- L.DomUtil.addClass(this._zoomInButton, className);\r
- }\r
- }\r
-});\r
-\r
-L.Map.mergeOptions({\r
- zoomControl: false,\r
- zoomsliderControl: true\r
-});\r
-\r
-L.Map.addInitHook(function () {\r
- if (this.options.zoomsliderControl) {\r
- L.control.zoomslider().addTo(this);\r
- }\r
-});\r
-\r
-L.control.zoomslider = function (options) {\r
- return new L.Control.Zoomslider(options);\r
-};\r
-\r
-\r
-L.BoundedDraggable = L.Draggable.extend({\r
- initialize: function(element, dragStartTarget, bounds) {\r
- L.Draggable.prototype.initialize.call(this, element, dragStartTarget);\r
- this._bounds = bounds;\r
- this.on('predrag', function() {\r
- if(!this._bounds.contains(this._newPos)){\r
- this._newPos = this._fitPoint(this._newPos);\r
- }\r
- }, this);\r
- },\r
- _fitPoint: function(point){\r
- var closest = new L.Point(\r
- Math.min(point.x, this._bounds.max.x),\r
- Math.min(point.y, this._bounds.max.y)\r
- );\r
- closest.x = Math.max(closest.x, this._bounds.min.x);\r
- closest.y = Math.max(closest.y, this._bounds.min.y);\r
- return closest;\r
- }\r
-});\r
+L.Control.Zoomslider = (function () {
+
+ var Knob = L.Draggable.extend({
+ initialize: function (element, stepHeight, knobHeight) {
+ L.Draggable.prototype.initialize.call(this, element, element);
+ this._element = element;
+
+ this._stepHeight = stepHeight;
+ this._knobHeight = knobHeight;
+
+ this.on('predrag', function () {
+ this._newPos.x = 0;
+ this._newPos.y = this._adjust(this._newPos.y);
+ }, this);
+ },
+
+ _adjust: function (y) {
+ var value = Math.round(this._toValue(y));
+ value = Math.max(0, Math.min(this._maxValue, value));
+ return this._toY(value);
+ },
+
+ // y = k*v + m
+ _toY: function (value) {
+ return this._k * value + this._m;
+ },
+ // v = (y - m) / k
+ _toValue: function (y) {
+ return (y - this._m) / this._k;
+ },
+
+ setSteps: function (steps) {
+ var sliderHeight = steps * this._stepHeight;
+ this._maxValue = steps - 1;
+
+ // conversion parameters
+ // the conversion is just a common linear function.
+ this._k = -this._stepHeight;
+ this._m = sliderHeight - (this._stepHeight + this._knobHeight) / 2;
+ },
+
+ setPosition: function (y) {
+ L.DomUtil.setPosition(this._element,
+ L.point(0, this._adjust(y)));
+ },
+
+ setValue: function (v) {
+ this.setPosition(this._toY(v));
+ },
+
+ getValue: function () {
+ return this._toValue(L.DomUtil.getPosition(this._element).y);
+ }
+ });
+
+ var Zoomslider = L.Control.extend({
+ options: {
+ position: 'topleft',
+ // Height of zoom-slider.png in px
+ stepHeight: 9,
+ // Height of the knob div in px
+ knobHeight: 5,
+ styleNS: 'leaflet-control-zoomslider'
+ },
+
+ onAdd: function (map) {
+ var container = L.DomUtil.create('div', this.options.styleNS + ' leaflet-bar');
+
+ L.DomEvent.disableClickPropagation(container);
+
+ this._map = map;
+
+ this._zoomInButton = this._createZoomButton(
+ 'in', 'top', container, this._zoomIn);
+
+ this._sliderElem = L.DomUtil.create(
+ 'div',
+ this.options.styleNS + "-slider leaflet-bar-part",
+ container);
+
+ this._zoomOutButton = this._createZoomButton(
+ 'out', 'bottom', container, this._zoomOut);
+
+ map .on('zoomlevelschange', this._refresh, this)
+ .on("zoomend", this._updateKnob, this)
+ .on("zoomend", this._updateDisabled, this)
+ .whenReady(this._createSlider, this)
+ .whenReady(this._createKnob, this)
+ .whenReady(this._refresh, this);
+
+ return container;
+ },
+
+ onRemove: function (map) {
+ map .off("zoomend", this._updateKnob)
+ .off("zoomend", this._updateDisabled)
+ .off('zoomlevelschange', this._refresh);
+ },
+
+ _refresh: function () {
+ var zoomLevels = this._zoomLevels();
+ if (zoomLevels < Infinity && this._knob && this._sliderBody) {
+ this._setSteps(zoomLevels);
+ this._updateKnob();
+ this._updateDisabled();
+ }
+ },
+ _zoomLevels: function () {
+ return this._map.getMaxZoom() - this._map.getMinZoom() + 1;
+ },
+
+ _createSlider: function () {
+ this._sliderBody = L.DomUtil.create('div',
+ this.options.styleNS + '-slider-body',
+ this._sliderElem);
+ L.DomEvent.on(this._sliderBody, 'click', this._onSliderClick, this);
+ },
+
+ _createKnob: function () {
+ var knobElem = L.DomUtil.create('div', this.options.styleNS + '-slider-knob',
+ this._sliderBody);
+ L.DomEvent.disableClickPropagation(knobElem);
+
+ this._knob = new Knob(knobElem,
+ this.options.stepHeight,
+ this.options.knobHeight)
+ .on('dragend', this._updateZoom, this);
+ this._knob.enable();
+ },
+
+ _onSliderClick: function (e) {
+ var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e);
+ var y = L.DomEvent.getMousePosition(first).y
+ - L.DomUtil.getViewportOffset(this._sliderBody).y; // Cache this?
+ this._knob.setPosition(y);
+ this._updateZoom();
+ },
+
+ _zoomIn: function (e) {
+ this._map.zoomIn(e.shiftKey ? 3 : 1);
+ },
+ _zoomOut: function (e) {
+ this._map.zoomOut(e.shiftKey ? 3 : 1);
+ },
+
+ _createZoomButton: function (zoomDir, end, container, fn) {
+ var barPart = 'leaflet-bar-part',
+ classDef = this.options.styleNS + '-' + zoomDir
+ + ' ' + barPart
+ + ' ' + barPart + '-' + end,
+ title = 'Zoom ' + zoomDir,
+ link = L.DomUtil.create('a', classDef, container);
+ link.href = '#';
+ link.title = title;
+
+ L.DomEvent
+ .on(link, 'click', L.DomEvent.preventDefault)
+ .on(link, 'click', fn, this);
+
+ return link;
+ },
+ _toZoomLevel: function (value) {
+ return value + this._map.getMinZoom();
+ },
+ _toValue: function (zoomLevel) {
+ return zoomLevel - this._map.getMinZoom();
+ },
+ _setSteps: function (zoomLevels) {
+ this._sliderBody.style.height
+ = (this.options.stepHeight * zoomLevels) + "px";
+ this._knob.setSteps(zoomLevels);
+ },
+ _updateZoom: function () {
+ this._map.setZoom(this._toZoomLevel(this._knob.getValue()));
+ },
+ _updateKnob: function () {
+ if (this._knob) {
+ this._knob.setValue(this._toValue(this._map.getZoom()));
+ }
+ },
+ _updateDisabled: function () {
+ var map = this._map,
+ className = this.options.styleNS + '-disabled';
+
+ L.DomUtil.removeClass(this._zoomInButton, className);
+ L.DomUtil.removeClass(this._zoomOutButton, className);
+
+ if (map.getZoom() === map.getMinZoom()) {
+ L.DomUtil.addClass(this._zoomOutButton, className);
+ }
+ if (map.getZoom() === map.getMaxZoom()) {
+ L.DomUtil.addClass(this._zoomInButton, className);
+ }
+ }
+ });
+ return Zoomslider;
+})();
+
+L.Map.mergeOptions({
+ zoomControl: false,
+ zoomsliderControl: true
+});
+
+L.Map.addInitHook(function () {
+ if (this.options.zoomsliderControl) {
+ this.zoomsliderControl = new L.Control.Zoomslider();
+ this.addControl(this.zoomsliderControl);
+ }
+});
+
+L.control.zoomslider = function (options) {
+ return new L.Control.Zoomslider(options);
+};