From: Tom MacWright Date: Tue, 7 Aug 2012 20:50:22 +0000 (-0400) Subject: Replace standard PanZoomBar control with new SimplePanZoom control X-Git-Tag: live~5484 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/b812c070f127e8aacf6dd5dc2f5c0cae696ad3ac Replace standard PanZoomBar control with new SimplePanZoom control --- diff --git a/app/assets/javascripts/map.js.erb b/app/assets/javascripts/map.js.erb index 82826ebfb..50b0fe441 100644 --- a/app/assets/javascripts/map.js.erb +++ b/app/assets/javascripts/map.js.erb @@ -14,7 +14,7 @@ function createMap(divName, options) { new SimpleLayerSwitcher(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.Zoom(), - new OpenLayers.Control.PanZoomBar(), + new OpenLayers.Control.SimplePanZoom(), new OpenLayers.Control.ScaleLine({geodesic: true}) ], numZoomLevels: 20, diff --git a/app/assets/javascripts/openlayers.js.erb b/app/assets/javascripts/openlayers.js.erb index b493a0517..ebb9578a3 100644 --- a/app/assets/javascripts/openlayers.js.erb +++ b/app/assets/javascripts/openlayers.js.erb @@ -1,6 +1,7 @@ //= require OpenLayers //= require OpenStreetMap //= require SimpleLayerSwitcher +//= require SimplePanZoom OpenLayers.Util.imageURLs = { "404.png": "<%= asset_path 'img/404.png' %>", diff --git a/app/assets/openlayers/SimplePanZoom.js b/app/assets/openlayers/SimplePanZoom.js new file mode 100644 index 000000000..a1a389d90 --- /dev/null +++ b/app/assets/openlayers/SimplePanZoom.js @@ -0,0 +1,355 @@ +/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the 2-clause BSD license. + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + + +/** + * @requires OpenLayers/Control/PanZoom.js + */ + +/** + * Class: OpenLayers.Control.PanZoomBar + * The PanZoomBar is a visible control composed of a + * and a . + * By default it is displayed in the upper left corner of the map as 4 + * directional arrows above a vertical slider. + * + * Inherits from: + * - + */ +OpenLayers.Control.SimplePanZoom = OpenLayers.Class(OpenLayers.Control.PanZoom, { + + /** + * APIProperty: zoomStopWidth + */ + zoomStopWidth: 18, + + /** + * APIProperty: zoomStopHeight + */ + zoomStopHeight: 7, + + /** + * Property: slider + */ + slider: null, + + /** + * Property: sliderEvents + * {} + */ + sliderEvents: null, + + /** + * Property: zoombarDiv + * {DOMElement} + */ + zoombarDiv: null, + + /** + * APIProperty: zoomWorldIcon + * {Boolean} + */ + zoomWorldIcon: false, + + /** + * APIProperty: panIcons + * {Boolean} Set this property to false not to display the pan icons. If + * false the zoom world icon is placed under the zoom bar. Defaults to + * true. + */ + panIcons: true, + + /** + * APIProperty: forceFixedZoomLevel + * {Boolean} Force a fixed zoom level even though the map has + * fractionalZoom + */ + forceFixedZoomLevel: false, + + /** + * Property: mouseDragStart + * {} + */ + mouseDragStart: null, + + /** + * Property: deltaY + * {Number} The cumulative vertical pixel offset during a zoom bar drag. + */ + deltaY: null, + + /** + * Property: zoomStart + * {} + */ + zoomStart: null, + + /** + * Constructor: OpenLayers.Control.PanZoomBar + */ + buttons: null, + + /** + * APIMethod: destroy + */ + destroy: function() { + + this._removeZoomBar(); + + this.map.events.un({ + "changebaselayer": this.redraw, + "updatesize": this.redraw, + scope: this + }); + + OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments); + + delete this.mouseDragStart; + delete this.zoomStart; + }, + + /** + * Method: setMap + * + * Parameters: + * map - {} + */ + setMap: function(map) { + OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments); + this.map.events.on({ + "changebaselayer": this.redraw, + "updatesize": this.redraw, + scope: this + }); + }, + + /** + * Method: redraw + * clear the div and start over. + */ + redraw: function() { + if (this.div !== null) { + this.removeButtons(); + this._removeZoomBar(); + } + this.draw(); + }, + + /** + * Method: draw + * + * Parameters: + * px - {} + */ + draw: function(px) { + // initialize our internal div + OpenLayers.Control.prototype.draw.apply(this, arguments); + px = this.position.clone(); + + // place the controls + this.buttons = []; + var ids = ['panup', 'panleft', 'panright', 'pandown', 'zoomout', 'zoomin']; + + for (var i = 0; i < ids.length; i++) { + var b = document.createElement('div'); + b.id = ids[i]; + b.action = ids[i]; + b.className = 'button olButton'; + this.div.appendChild(b); + this.buttons.push(b); + } + + this._addZoomBar(); + return this.div; + }, + + /** + * Method: _addZoomBar + * + * Parameters: + * centered - {} where zoombar drawing is to start. + */ + _addZoomBar:function() { + var id = this.id + "_" + this.map.id; + var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom(); + var slider = document.createElement('div'); + slider.id = 'slider'; + slider.className = 'button'; + slider.style.cursor = 'move'; + this.slider = slider; + + this.sliderEvents = new OpenLayers.Events(this, slider, null, true, + { includeXY: true }); + this.sliderEvents.on({ + "touchstart": this.zoomBarDown, + "touchmove": this.zoomBarDrag, + "touchend": this.zoomBarUp, + "mousedown": this.zoomBarDown, + "mousemove": this.zoomBarDrag, + "mouseup": this.zoomBarUp + }); + + var height = this.zoomStopHeight * (this.map.getNumZoomLevels()); + + // this is the background image + var div = document.createElement('div'); + div.className = 'button olButton'; + div.id = 'zoombar'; + this.zoombarDiv = div; + + this.div.appendChild(div); + this.startTop = 75; + this.div.appendChild(slider); + + this.map.events.register("zoomend", this, this.moveZoomBar); + }, + + /** + * Method: _removeZoomBar + */ + _removeZoomBar: function() { + this.sliderEvents.un({ + "touchstart": this.zoomBarDown, + "touchmove": this.zoomBarDrag, + "touchend": this.zoomBarUp, + "mousedown": this.zoomBarDown, + "mousemove": this.zoomBarDrag, + "mouseup": this.zoomBarUp + }); + this.sliderEvents.destroy(); + + this.div.removeChild(this.zoombarDiv); + this.zoombarDiv = null; + this.div.removeChild(this.slider); + this.slider = null; + + this.map.events.unregister("zoomend", this, this.moveZoomBar); + }, + + /** + * Method: onButtonClick + * + * Parameters: + * evt - {Event} + */ + onButtonClick: function(evt) { + OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this, arguments); + if (evt.buttonElement === this.zoombarDiv) { + var levels = evt.buttonXY.y / this.zoomStopHeight; + if (this.forceFixedZoomLevel || !this.map.fractionalZoom) { + levels = Math.floor(levels); + } + var zoom = (this.map.getNumZoomLevels() - 1) - levels; + zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1); + this.map.zoomTo(zoom); + } + }, + + /** + * Method: passEventToSlider + * This function is used to pass events that happen on the div, or the map, + * through to the slider, which then does its moving thing. + * + * Parameters: + * evt - {} + */ + passEventToSlider:function(evt) { + this.sliderEvents.handleBrowserEvent(evt); + }, + + /* + * Method: zoomBarDown + * event listener for clicks on the slider + * + * Parameters: + * evt - {} + */ + zoomBarDown:function(evt) { + if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) { + return; + } + this.map.events.on({ + "touchmove": this.passEventToSlider, + "mousemove": this.passEventToSlider, + "mouseup": this.passEventToSlider, + scope: this + }); + this.mouseDragStart = evt.xy.clone(); + this.zoomStart = evt.xy.clone(); + this.div.style.cursor = "move"; + // reset the div offsets just in case the div moved + this.zoombarDiv.offsets = null; + OpenLayers.Event.stop(evt); + }, + + /* + * Method: zoomBarDrag + * This is what happens when a click has occurred, and the client is + * dragging. Here we must ensure that the slider doesn't go beyond the + * bottom/top of the zoombar div, as well as moving the slider to its new + * visual location + * + * Parameters: + * evt - {} + */ + zoomBarDrag: function(evt) { + if (this.mouseDragStart !== null) { + var deltaY = this.mouseDragStart.y - evt.xy.y; + var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv); + if ((evt.clientY - offsets[1]) > 0 && + (evt.clientY - offsets[1]) < 140) { + var newTop = parseInt(this.slider.style.top, 10) - deltaY; + this.slider.style.top = newTop + "px"; + this.mouseDragStart = evt.xy.clone(); + } + // set cumulative displacement + this.deltaY = this.zoomStart.y - evt.xy.y; + OpenLayers.Event.stop(evt); + } + }, + + /* + * Method: zoomBarUp + * Perform cleanup when a mouseup event is received -- discover new zoom + * level and switch to it. + * + * Parameters: + * evt - {} + */ + zoomBarUp: function(evt) { + if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") { + return; + } + if (this.mouseDragStart) { + this.div.style.cursor = ""; + this.map.events.un({ + "touchmove": this.passEventToSlider, + "mouseup": this.passEventToSlider, + "mousemove": this.passEventToSlider, + scope: this + }); + var zoomLevel = this.map.zoom; + zoomLevel += this.deltaY/this.zoomStopHeight; + zoomLevel = Math.max(Math.round(zoomLevel), 0); + this.map.zoomTo(zoomLevel); + this.mouseDragStart = null; + this.zoomStart = null; + this.deltaY = 0; + OpenLayers.Event.stop(evt); + } + }, + + /* + * Method: moveZoomBar + * Change the location of the slider to match the current zoom level. + */ + moveZoomBar:function() { + var newTop = + ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) * + this.zoomStopHeight + this.startTop; + this.slider.style.top = newTop + "px"; + }, + CLASS_NAME: "OpenLayers.Control.SimplePanZoom" +}); diff --git a/app/assets/openlayers/theme/openstreetmap/SimplePanZoom.css.scss b/app/assets/openlayers/theme/openstreetmap/SimplePanZoom.css.scss new file mode 100644 index 000000000..898640ccb --- /dev/null +++ b/app/assets/openlayers/theme/openstreetmap/SimplePanZoom.css.scss @@ -0,0 +1,76 @@ +.olControlSimplePanZoom { + top: 10px; + right: 10px; +} + +.olControlSimplePanZoom .button { + background-image: image-url("theme/openstreetmap/img/map_sprite.png"); + position: absolute; + background-repeat: no-repeat; + cursor: hand; + cursor: pointer; +} + +.olControlSimplePanZoom #panup { + left: 10px; + width: 25px; + height: 13px; + background-position: -15px -5px; +} + +.olControlSimplePanZoom #pandown { + left: 10px; + top: 36px; + width: 25px; + height: 15px; + background-position: -15px -40px; +} + +.olControlSimplePanZoom #panleft { + top: 13px; + width: 25px; + height: 24px; + background-position: -5px -17px; +} + +.olControlSimplePanZoom #panright { + top: 13px; + width: 25px; + height: 24px; + left: 25px; + background-position: -30px -17px; +} + +.olControlSimplePanZoom #zoomin { + top: 50px; + width: 26px; + height: 20px; + left: 10px; + background-position: -15px -61px; +} + +.olControlSimplePanZoom #zoomout { + top: 210px; + width: 26px; + height: 20px; + left: 10px; + background-position: -15px -220px; +} + +.olControlSimplePanZoom #slider { + top: 75px; + width: 25px; + height: 10px; + left: 10px; + -webkit-transition: top 100ms linear; + background-position: -77px -58px; + pointer: move; + cursor: move; +} +.olControlSimplePanZoom #zoombar { + top: 70px; + width: 26px; + height: 140px; + left: 10px; + background-position: -15px -80px; +} diff --git a/app/assets/openlayers/theme/openstreetmap/img/map_sprite.png b/app/assets/openlayers/theme/openstreetmap/img/map_sprite.png new file mode 100644 index 000000000..99734b12f Binary files /dev/null and b/app/assets/openlayers/theme/openstreetmap/img/map_sprite.png differ diff --git a/app/assets/openlayers/theme/openstreetmap/style.css.scss b/app/assets/openlayers/theme/openstreetmap/style.css.scss index 6c6cf3cd3..b082c9933 100644 --- a/app/assets/openlayers/theme/openstreetmap/style.css.scss +++ b/app/assets/openlayers/theme/openstreetmap/style.css.scss @@ -1,6 +1,7 @@ /* *= require theme/default/style *= require theme/openstreetmap/SimpleLayerSwitcher + *= require theme/openstreetmap/SimplePanZoom */ .olControlOverviewMapExtentRectangle { diff --git a/app/assets/stylesheets/small.css.scss b/app/assets/stylesheets/small.css.scss index b5adaa794..66cc68655 100644 --- a/app/assets/stylesheets/small.css.scss +++ b/app/assets/stylesheets/small.css.scss @@ -91,7 +91,7 @@ h1 { border: 0; } -.olControlPanZoomBar { +.olControlSimplePanZoom { display: none; }