flag on the Events object is set to true. This ends up meaning that we save a lot of unneccesary getMousePosition calls because (for example) the layer doesn't need to include the .xy property. In addition, we add in speed improvements via caching to the getMousePosition, courtesy the work from pgiraud (which was worked on further by tcoulter) -- this results in significantly improved getMousePosition performance improvements in 'real life' situations that are more like the cases that people use OpenLayers, with a higher number of containing divs (and also clearly demonstrate a gain in performance even in the simple case.) The end result is: * In typical map movement over the map, (n / n+1) fewer calls to getMousePosition, where n is the number of active layers when dragging over the map. * In the simple case, 40% faster getMousePosition performance -- and in more complex cases, significantly more performance improvements. To drop the former improvement, which may affect some applications (as described in the includeXY documentation) simply set: OpenLayers.Events.prototype.includeXY = true; This will restore the 'every element has an xy property always' behavior that was the case beore this patch. r=me,tschaub, work by pgiraud related to (See #1509), and (Closes #1459) git-svn-id: http://svn.openlayers.org/trunk/openlayers@7615 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
351 lines
10 KiB
JavaScript
351 lines
10 KiB
JavaScript
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
|
|
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
|
|
* full text of the license. */
|
|
|
|
|
|
/**
|
|
* @requires OpenLayers/Control/PanZoom.js
|
|
*/
|
|
|
|
/**
|
|
* Class: OpenLayers.Control.PanZoomBar
|
|
*
|
|
* 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,
|
|
|
|
/**
|
|
* Property: divEvents
|
|
* {<OpenLayers.Events>}
|
|
*/
|
|
divEvents: null,
|
|
|
|
/**
|
|
* Property: zoomWorldIcon
|
|
* {Boolean}
|
|
*/
|
|
zoomWorldIcon: false,
|
|
|
|
/**
|
|
* Constructor: OpenLayers.Control.PanZoomBar
|
|
*/
|
|
initialize: function() {
|
|
OpenLayers.Control.PanZoom.prototype.initialize.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* APIMethod: destroy
|
|
*/
|
|
destroy: function() {
|
|
|
|
this.div.removeChild(this.slider);
|
|
this.slider = null;
|
|
|
|
this.sliderEvents.destroy();
|
|
this.sliderEvents = null;
|
|
|
|
this.div.removeChild(this.zoombarDiv);
|
|
this.zoomBarDiv = null;
|
|
|
|
this.divEvents.destroy();
|
|
this.divEvents = null;
|
|
|
|
this.map.events.un({
|
|
"zoomend": this.moveZoomBar,
|
|
"changebaselayer": this.redraw,
|
|
scope: this
|
|
});
|
|
|
|
OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* Method: setMap
|
|
*
|
|
* Parameters:
|
|
* map - {<OpenLayers.Map>}
|
|
*/
|
|
setMap: function(map) {
|
|
OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
|
|
this.map.events.register("changebaselayer", this, this.redraw);
|
|
},
|
|
|
|
/**
|
|
* Method: redraw
|
|
* clear the div and start over.
|
|
*/
|
|
redraw: function() {
|
|
if (this.div != null) {
|
|
this.div.innerHTML = "";
|
|
}
|
|
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 = new OpenLayers.Size(18,18);
|
|
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);
|
|
return this.div;
|
|
},
|
|
|
|
/**
|
|
* Method: _addZoomBar
|
|
*
|
|
* Parameters:
|
|
* location - {<OpenLayers.Pixel>} where zoombar drawing is to start.
|
|
*/
|
|
_addZoomBar:function(centered) {
|
|
var imgLocation = OpenLayers.Util.getImagesLocation();
|
|
|
|
var id = "OpenLayers_Control_PanZoomBar_Slider" + this.map.id;
|
|
var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
|
|
var slider = OpenLayers.Util.createAlphaImageDiv(id,
|
|
centered.add(-1, zoomsToEnd * this.zoomStopHeight),
|
|
new OpenLayers.Size(20,9),
|
|
imgLocation+"slider.png",
|
|
"absolute");
|
|
this.slider = slider;
|
|
|
|
this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
|
|
{includeXY: true});
|
|
this.sliderEvents.on({
|
|
"mousedown": this.zoomBarDown,
|
|
"mousemove": this.zoomBarDrag,
|
|
"mouseup": this.zoomBarUp,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
|
|
var sz = new OpenLayers.Size();
|
|
sz.h = this.zoomStopHeight * this.map.getNumZoomLevels();
|
|
sz.w = this.zoomStopWidth;
|
|
var div = null;
|
|
|
|
if (OpenLayers.Util.alphaHack()) {
|
|
var id = "OpenLayers_Control_PanZoomBar" + this.map.id;
|
|
div = OpenLayers.Util.createAlphaImageDiv(id, centered,
|
|
new OpenLayers.Size(sz.w,
|
|
this.zoomStopHeight),
|
|
imgLocation + "zoombar.png",
|
|
"absolute", null, "crop");
|
|
div.style.height = sz.h + "px";
|
|
} else {
|
|
div = OpenLayers.Util.createDiv(
|
|
'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
|
|
centered,
|
|
sz,
|
|
imgLocation+"zoombar.png");
|
|
}
|
|
|
|
this.zoombarDiv = div;
|
|
|
|
this.divEvents = new OpenLayers.Events(this, div, null, true,
|
|
{includeXY: true});
|
|
this.divEvents.on({
|
|
"mousedown": this.divClick,
|
|
"mousemove": this.passEventToSlider,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
|
|
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());
|
|
return centered;
|
|
},
|
|
|
|
/*
|
|
* 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: divClick
|
|
* Picks up on clicks directly on the zoombar div
|
|
* and sets the zoom level appropriately.
|
|
*/
|
|
divClick: function (evt) {
|
|
if (!OpenLayers.Event.isLeftClick(evt)) {
|
|
return;
|
|
}
|
|
var y = evt.xy.y;
|
|
var top = OpenLayers.Util.pagePosition(evt.object)[1];
|
|
var levels = (y - top)/this.zoomStopHeight;
|
|
if(!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);
|
|
OpenLayers.Event.stop(evt);
|
|
},
|
|
|
|
/*
|
|
* Method: zoomBarDown
|
|
* event listener for clicks on the slider
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
zoomBarDown:function(evt) {
|
|
if (!OpenLayers.Event.isLeftClick(evt)) {
|
|
return;
|
|
}
|
|
this.map.events.on({
|
|
"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();
|
|
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)) {
|
|
return;
|
|
}
|
|
if (this.zoomStart) {
|
|
this.div.style.cursor="";
|
|
this.map.events.un({
|
|
"mouseup": this.passEventToSlider,
|
|
"mousemove": this.passEventToSlider,
|
|
scope: this
|
|
});
|
|
var deltaY = this.zoomStart.y - evt.xy.y;
|
|
var zoomLevel = this.map.zoom;
|
|
if (this.map.fractionalZoom) {
|
|
zoomLevel += deltaY/this.zoomStopHeight;
|
|
zoomLevel = Math.min(Math.max(zoomLevel, 0),
|
|
this.map.getNumZoomLevels() - 1);
|
|
} else {
|
|
zoomLevel += Math.round(deltaY/this.zoomStopHeight);
|
|
}
|
|
this.map.zoomTo(zoomLevel);
|
|
this.moveZoomBar();
|
|
this.mouseDragStart = null;
|
|
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"
|
|
});
|