This can be used by zoom slider controls, e.g. the GeoExt.ZoomSlider. Note that adjustZoom now also respects the map's fractionalZoom setting.
408 lines
12 KiB
JavaScript
408 lines
12 KiB
JavaScript
/* 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
|
|
* <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>.
|
|
* 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.PanZoom>
|
|
*/
|
|
OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
|
|
|
|
/**
|
|
* APIProperty: zoomStopWidth
|
|
*/
|
|
zoomStopWidth: 18,
|
|
|
|
/**
|
|
* APIProperty: zoomStopHeight
|
|
*/
|
|
zoomStopHeight: 11,
|
|
|
|
/**
|
|
* Property: slider
|
|
*/
|
|
slider: null,
|
|
|
|
/**
|
|
* Property: sliderEvents
|
|
* {<OpenLayers.Events>}
|
|
*/
|
|
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
|
|
* {<OpenLayers.Pixel>}
|
|
*/
|
|
mouseDragStart: null,
|
|
|
|
/**
|
|
* Property: deltaY
|
|
* {Number} The cumulative vertical pixel offset during a zoom bar drag.
|
|
*/
|
|
deltaY: null,
|
|
|
|
/**
|
|
* Property: zoomStart
|
|
* {<OpenLayers.Pixel>}
|
|
*/
|
|
zoomStart: null,
|
|
|
|
/**
|
|
* Constructor: OpenLayers.Control.PanZoomBar
|
|
*/
|
|
|
|
/**
|
|
* 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 - {<OpenLayers.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 - {<OpenLayers.Pixel>}
|
|
*/
|
|
draw: function(px) {
|
|
// initialize our internal div
|
|
OpenLayers.Control.prototype.draw.apply(this, arguments);
|
|
px = this.position.clone();
|
|
|
|
// place the controls
|
|
this.buttons = [];
|
|
|
|
var sz = {w: 18, h: 18};
|
|
if (this.panIcons) {
|
|
var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
|
|
var wposition = sz.w;
|
|
|
|
if (this.zoomWorldIcon) {
|
|
centered = new OpenLayers.Pixel(px.x+sz.w, px.y);
|
|
}
|
|
|
|
this._addButton("panup", "north-mini.png", centered, sz);
|
|
px.y = centered.y+sz.h;
|
|
this._addButton("panleft", "west-mini.png", px, sz);
|
|
if (this.zoomWorldIcon) {
|
|
this._addButton("zoomworld", "zoom-world-mini.png", px.add(sz.w, 0), sz);
|
|
|
|
wposition *= 2;
|
|
}
|
|
this._addButton("panright", "east-mini.png", px.add(wposition, 0), sz);
|
|
this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz);
|
|
this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz);
|
|
centered = this._addZoomBar(centered.add(0, sz.h*4 + 5));
|
|
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
|
|
}
|
|
else {
|
|
this._addButton("zoomin", "zoom-plus-mini.png", px, sz);
|
|
centered = this._addZoomBar(px.add(0, sz.h));
|
|
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
|
|
if (this.zoomWorldIcon) {
|
|
centered = centered.add(0, sz.h+3);
|
|
this._addButton("zoomworld", "zoom-world-mini.png", centered, sz);
|
|
}
|
|
}
|
|
return this.div;
|
|
},
|
|
|
|
/**
|
|
* Method: _addZoomBar
|
|
*
|
|
* Parameters:
|
|
* centered - {<OpenLayers.Pixel>} where zoombar drawing is to start.
|
|
*/
|
|
_addZoomBar:function(centered) {
|
|
var imgLocation = OpenLayers.Util.getImageLocation("slider.png");
|
|
var id = this.id + "_" + this.map.id;
|
|
var minZoom = this.map.getMinZoom();
|
|
var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
|
|
var slider = OpenLayers.Util.createAlphaImageDiv(id,
|
|
centered.add(-1, zoomsToEnd * this.zoomStopHeight),
|
|
{w: 20, h: 9},
|
|
imgLocation,
|
|
"absolute");
|
|
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 sz = {
|
|
w: this.zoomStopWidth,
|
|
h: this.zoomStopHeight * (this.map.getNumZoomLevels() - minZoom)
|
|
};
|
|
var imgLocation = OpenLayers.Util.getImageLocation("zoombar.png");
|
|
var div = null;
|
|
|
|
if (OpenLayers.Util.alphaHack()) {
|
|
var id = this.id + "_" + this.map.id;
|
|
div = OpenLayers.Util.createAlphaImageDiv(id, centered,
|
|
{w: sz.w, h: this.zoomStopHeight},
|
|
imgLocation,
|
|
"absolute", null, "crop");
|
|
div.style.height = sz.h + "px";
|
|
} else {
|
|
div = OpenLayers.Util.createDiv(
|
|
'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
|
|
centered,
|
|
sz,
|
|
imgLocation);
|
|
}
|
|
div.style.cursor = "pointer";
|
|
div.className = "olButton";
|
|
this.zoombarDiv = div;
|
|
|
|
this.div.appendChild(div);
|
|
|
|
this.startTop = parseInt(div.style.top);
|
|
this.div.appendChild(slider);
|
|
|
|
this.map.events.register("zoomend", this, this.moveZoomBar);
|
|
|
|
centered = centered.add(0,
|
|
this.zoomStopHeight * (this.map.getNumZoomLevels() - minZoom));
|
|
return centered;
|
|
},
|
|
|
|
/**
|
|
* 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 - {<OpenLayers.Event>}
|
|
*/
|
|
passEventToSlider:function(evt) {
|
|
this.sliderEvents.handleBrowserEvent(evt);
|
|
},
|
|
|
|
/*
|
|
* Method: zoomBarDown
|
|
* event listener for clicks on the slider
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
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 - {<OpenLayers.Event>}
|
|
*/
|
|
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]) < parseInt(this.zoombarDiv.style.height) - 2) {
|
|
var newTop = parseInt(this.slider.style.top) - 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 - {<OpenLayers.Event>}
|
|
*/
|
|
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;
|
|
if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
|
|
zoomLevel += this.deltaY/this.zoomStopHeight;
|
|
zoomLevel = Math.min(Math.max(zoomLevel, 0),
|
|
this.map.getNumZoomLevels() - 1);
|
|
} else {
|
|
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 + 1;
|
|
this.slider.style.top = newTop + "px";
|
|
},
|
|
|
|
CLASS_NAME: "OpenLayers.Control.PanZoomBar"
|
|
}); |