概述:
在WebGIS开发中,经常会有用户提需求,要实现卷帘功能,卷帘功能主要是实现两张图之间的对比。在前文中,讲到了openlayers3以及Arcgis for js中卷帘的实现,在本文讲述如何在openlayers2中实现卷帘功能。
结果展示:
实现代码:
在此,扩展了一个名为Swipe的Control,Swipe的代码如下:(猛击)
- /*
- *
- * @requires OpenLayers/Control.js
- */
- /* The following globals are for JSLint */
- /* jslint browser: true, vars: true */
- /* global OpenLayers, escape */
- /** api: (define)
- * module = OpenLayers.Control
- * class = Swipe
- * base_link = `OpenLayers.Control <http://dev.openlayers.org/apidocs/files/OpenLayers/Control-js.html>`_
- */
- /** api: example
- * Sample code to add a swipe control(猛击)
- *
- * .. code-block:: javascript
- *
- * var map = new new OpenLayers.Map("mymap");
- * var Swipe = new OpenLayers.Control.Swipe({map: map});
- * map.addControls([swipe]);
- * Swipe.activate();
- *
- */
- /** api: constructor
- * .. class:: Swipe(options)
- *
- * :param options: ``Object`` options
- *
- * :return: ``OpenLayers.Control.Swipe`` (猛击)
- *
- * Add a swipe control in the map
- */
- OpenLayers.Control.Swipe = OpenLayers.Class(OpenLayers.Control, {
- /** api: config[map]
- * ``OpenLayers.Map``
- * A `OpenLayers.Map <http://dev.openlayers.org/docs/files/OpenLayers/Map-js.html>`_ instance
- */
- map: null,
- width: 32,
- /** api: config[swipeRatio]
- * ``Number``
- * A number between 0 and 1 defining the position of the swipe relative to the map (from right to left)
- */
- swipeRatio: null,
- swipeLayer: null,
- isTitleVisible: false,
- isDragging: false,
- mouseDragStart: null,
- /**
- * Property: divEvents
- * {<OpenLayers.Events>}
- */
- divEvents: null,
- initialize: function (options) {
- "use strict";
- OpenLayers.Control.prototype.initialize.apply(
- this,
- arguments
- );
- // Manage position of swipe (猛击)
- if (this.map && this.map.swipeRatio) {
- // Swipe ratio can be set in the map (in order to manage permalink)
- this.setSwipeRatio(this.map.swipeRatio);
- } else {
- if (!this.swipeRatio) {
- // Default swipe ratio is 0.5
- this.setSwipeRatio(0.5);
- } else {
- // Swipe ratio can be set to the control
- this.setSwipeRatio(this.swipeRatio);
- }
- }
- },
- /**
- * Method: activate
- * Activates the control.
- *
- * Returns:
- * {Boolean} The control was effectively activated.
- */
- activate: function () {
- this.map.swipeActive = true;
- this.map.events.triggerEvent("changelayer", {
- layer: this.swipeLayer,
- property: "name"
- });
- OpenLayers.Control.prototype.activate.apply(this, arguments);
- this.map.events.on({
- "addlayer": this.handleAddLayer,
- "removelayer": this.handleRemoveLayer,
- "changelayer": this.handleChangeLayer,
- "updatesize": this.handleUpdateSize,
- "move": this.handleMove,
- "scope": this
- });
- if (this.isLayersInLayerSwitcher()) {
- this.div.style.display = 'block';
- this.viewBigArrow();
- }
- this.resize();
- return true;
- },
- /**
- * Method: deactivate (无效)
- * Deactivates the control.
- *
- * Returns:
- * {Boolean} The control was effectively deactivated.
- */
- deactivate: function () {
- this.map.swipeActive = false;
- this.map.events.triggerEvent("changelayer", {
- layer: this.swipeLayer,
- property: "name"
- });
- this.map.events.un({
- "addlayer": this.handleAddLayer,
- "removelayer": this.handleRemoveLayer,
- "changelayer": this.handleChangeLayer,
- "updatesize": this.handleUpdateSize,
- "move": this.handleMove,
- "scope": this
- });
- this.hideBigArrow();
- this.hideLayerTitle();
- this.div.style.display = 'none';
- if (this.swipeLayer) {
- if (this.swipeLayer.layers) {
- for (var i = this.swipeLayer.layers.length - 1; i >= 0; i--) {
- var layer = this.swipeLayer.layers[i];
- if (layer.div) {
- layer.div.style.clip = 'auto';
- }
- }
- } else {
- this.swipeLayer.div.style.clip = 'auto';
- }
- this.swipeLayer = null;
- }
- return OpenLayers.Control.prototype.deactivate.(无效)apply(
- this, arguments
- );
- },
- /**
- * Method: destroy
- * Destroy control.
- */
- destroy: function() {
- this.map.events.un({
- "addlayer": this.handleAddLayer,
- "removelayer": this.handleRemoveLayer,
- "changelayer": this.handleChangeLayer,
- "updatesize": this.handleUpdateSize,
- "scope": this
- });
- OpenLayers.Control.prototype.destroy.apply(this, arguments);
- },
- /**
- * Method: draw
- * Initialize control.
- *
- * Returns:
- * {DOMElement} A reference to the DIV DOMElement containing the control
- */
- draw: function() {
- OpenLayers.Control.prototype.draw.apply(this, arguments);
- this.elementLayer = document.createElement("div");
- this.div.appendChild(this.elementLayer);
- OpenLayers.Element.addClass(
- this.elementLayer,
- 'olControlSwipeLayerHide'
- );
- this.elementLayerSpan = document.createElement("span");
- this.div.appendChild(this.elementLayerSpan);
- OpenLayers.Element.addClass(
- this.elementLayerSpan,
- 'olControlSwipeLayerSpan'
- );
- this.elementLeft = document.createElement("div");
- this.div.appendChild(this.elementLeft);
- OpenLayers.Element.addClass(
- this.elementLeft,
- 'olControlArrowLeft'
- );
- this.elementRight = document.createElement("div");
- this.div.appendChild(this.elementRight);
- OpenLayers.Element.addClass(
- this.elementRight,
- 'olControlArrowRight'
- );
- OpenLayers.Control.prototype.draw.apply(this, arguments);
- this.divEvents = new OpenLayers.Events(this, this.div, null, true, {includeXY: true});
- this.divEvents.on({
- "touchstart": this.divDown,
- "touchmove": this.divDrag,
- "touchend": this.divUp,
- "mousedown": this.divDown,
- "mousemove": this.divDrag,
- "mouseup": this.divUp,
- "mouseover": this.divMouseOver,
- "mouseout": this.divMouseOut,
- scope: this
- });
- return this.div;
- },
- /*
- * Method: divMouseOver
- * event listener for onmouseover event
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- divMouseOver: function(ev) {
- OpenLayers.Element.addClass(
- this.div,
- 'olControlSwipeHover'
- );
- //this.viewLayerTitle();
- },
- hideBigArrow: function() {
- if (!this.isDragging) {
- this.elementLeft.style.display = "none";
- this.elementRight.style.display = "none";
- }
- },
- viewBigArrow: function() {
- if (!this.isDragging) {
- this.elementLeft.style.display = "block";
- this.elementRight.style.display = "block";
- }
- },
- /*
- * Method: divMouseOut
- * event listener for onmouseout event
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- divMouseOut: function(ev) {
- OpenLayers.Element.removeClass(
- this.div,
- 'olControlSwipeHover'
- );
- this.hideLayerTitle();
- this.viewBigArrow();
- },
- /**
- * Method: passEventToDiv
- * This function is used to pass events that happen on the map,
- * through to the div, which then does its moving thing.
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- passEventToDiv:function(evt) {
- this.divEvents.handleBrowserEvent(evt);
- },
- /*
- * Method: divDown
- * event listener for clicks on the div
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- divDown:function(evt) {
- if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
- return;
- }
- this.map.events.on({
- "touchmove": this.passEventToDiv,
- "mousemove": this.passEventToDiv,
- "mouseup": this.passEventToDiv,
- scope: this
- });
- this.mouseDragStart = evt.xy.clone();
- OpenLayers.Event.stop(evt);
- //this.viewLayerTitle();
- this.hideBigArrow();
- this.isDragging = true;
- return false;
- },
- /*
- * Method: divDrag
- * This is what happens when a click has occurred, and the client is
- * dragging. Here we must ensure that the div doesn't go beyond the
- * bottom/top of the zoombar div, as well as moving the div to its new
- * visual location
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- divDrag:function(evt) {
- if (this.mouseDragStart && this.isDragging) {
- var deltaX = this.mouseDragStart.x - evt.xy.x;
- var left = parseInt(this.div.style.left, 10);
- if ((left - deltaX) >= 0 &&
- (left - deltaX) <= (this.map.size.w - this.width)) {
- var delta = 0;
- if (OpenLayers.BROWSER_NAME === "msie" || OpenLayers.BROWSER_NAME === "safari") {
- delta = -1;
- }
- this.setSwipeRatio((left - deltaX) / (this.map.size.w - this.width + delta));
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- this.mouseDragStart = evt.xy.clone();
- }
- OpenLayers.Event.stop(evt);
- }
- return false;
- },
- /*
- * Method: divUp
- * Perform cleanup when a mouseup event is received
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- divUp:function(evt) {
- this.map.events.un({
- "touchmove": this.passEventToDiv,
- "mousemove": this.passEventToDiv,
- "mouseup": this.passEventToDiv,
- scope: this
- });
- if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
- return;
- }
- if (this.mouseDragStart) {
- this.mouseDragStart = null;
- }
- this.isDragging = false;
- this.viewBigArrow();
- if (evt.type === "touchend") {
- this.hideLayerTitle();
- }
- OpenLayers.Event.stop(evt);
- return false;
- },
- /*
- * Method: clipFirstLayer
- * Clip the first layer present in the layer switcher
- */
- clipFirstLayer: function() {
- var newFirstLayer = this.getFirstLayerInLayerSwitcher();
- if (this.swipeLayer) {
- if (newFirstLayer.id !== this.swipeLayer.id) {
- if (this.swipeLayer.layers) {
- for (var i = this.swipeLayer.layers.length - 1; i >= 0; i--) {
- var layer = this.swipeLayer.layers[i];
- if (layer.div) {
- layer.div.style.clip = 'auto';
- }
- }
- } else {
- this.swipeLayer.div.style.clip = 'auto';
- }
- }
- }
- if (newFirstLayer) {
- var width = this.map.getCurrentSize().w;
- var height = this.map.getCurrentSize().h;
- // slider position in pixels
- var s = parseInt(width * this.getSwipeRatio() * ((this.map.getCurrentSize().w - this.width) / this.map.getCurrentSize().w), 10);
- // cliping rectangle
- var top = -this.map.layerContainerOriginPx.y;
- var bottom = top + height;
- var left = -this.map.layerContainerOriginPx.x;
- var right = left + s + Math.ceil((this.width - 1) / 2);
- //Syntax for clip "rect(top,right,bottom,left)"
- var clip = "rect(" + top + "px " + right + "px " + bottom + "px " + left + "px)";
- this.swipeLayer = newFirstLayer;
- if (this.swipeLayer.layers) {
- for (var i = this.swipeLayer.layers.length - 1; i >= 0; i--) {
- var layer = this.swipeLayer.layers[i];
- if (layer.div) {
- layer.div.style.clip = clip;
- }
- }
- } else {
- this.swipeLayer.div.style.clip = clip;
- }
- }
- },
- /*
- * Method: handleAddLayer
- * Triggered when a new layer is added
- *
- * Parameters:
- * object - {<OpenLayers.Event>}
- */
- handleAddLayer: function (object) {
- if (this.isLayersInLayerSwitcher()) {
- this.div.style.display = 'block';
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- } else {
- this.div.style.display = 'none';
- this.swipeLayer = null;
- }
- },
- viewLayerTitle: function() {
- if (!this.isTitleVisible && !this.isDragging) {
- if (this.swipeLayer) {
- var content = " " + this.swipeLayer.name;
- this.elementLayer.innerHTML = content;
- this.elementLayerSpan.innerHTML = content;
- OpenLayers.Element.addClass(
- this.elementLayer,
- 'olControlSwipeLayerView'
- );
- OpenLayers.Element.removeClass(
- this.elementLayer,
- 'olControlSwipeLayerHide'
- );
- var width = parseInt(this.elementLayerSpan.offsetWidth) + 5;
- this.elementLayer.style.width = width + "px";
- this.elementLayer.style.marginLeft = "-" + width + "px";
- }
- }
- this.isTitleVisible = true;
- },
- hideLayerTitle: function() {
- if (!this.isDragging) {
- this.elementLayer.innerHTML = '';
- this.isTitleVisible = false;
- OpenLayers.Element.addClass(
- this.elementLayer,
- 'olControlSwipeLayerHide'
- );
- OpenLayers.Element.removeClass(
- this.elementLayer,
- 'olControlSwipeLayerView'
- );
- }
- },
- /*
- * Method: handleRemoveLayer
- * Triggered when a new layer is removed
- *
- * Parameters:
- * object - {<OpenLayers.Event>}
- */
- handleRemoveLayer: function (object) {
- if (this.isLayersInLayerSwitcher()) {
- this.div.style.display = 'block';
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- } else {
- this.div.style.display = 'none';
- this.swipeLayer = null;
- }
- },
- /*
- * Method: handleChangeLayer
- * Triggered when the layer order is changed
- *
- * Parameters:
- * object - {<OpenLayers.Event>}
- */
- handleChangeLayer: function (object) {
- if (object.property === 'order') {
- if (this.isLayersInLayerSwitcher()) {
- this.div.style.display = 'block';
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- } else {
- this.div.style.display = 'none';
- this.swipeLayer = null;
- }
- }
- },
- /*
- * Method: handleUpdateSize
- * Triggered when the map size changed. In this case the swipe control is upda(猛击)ted accordingly.
- *
- * Parameters:
- * object - {<OpenLayers.Event>}
- */
- handleUpdateSize: function (object) {
- //we have to delay this on Android devices
- if (navigator.userAgent.toLowerCase().indexOf("android") > 0) {
- var self = this;
- setTimeout(function() {
- self.resize();
- }, 10);
- } else {
- this.resize();
- }
- },
- /*
- * Method: handleMove
- * Triggered when the map is moved. In this case, the clip ares has to be updated
- *
- * Parameters:
- * object - {<OpenLayers.Event>}
- */
- handleMove: function (object) {
- this.clipFirstLayer();
- },
- /*
- * Method: resize
- * Resize the swipe and upd(猛击)ate the first layer clipping
- */
- resize: function() {
- this.div.style.height = this.map.getCurrentSize().h + 'px';
- this.div.style.width = this.width + 'px';
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- var topPosition = (this.map.getCurrentSize().h / 2) - 32;
- this.elementLeft.style.marginTop = topPosition + 'px';
- this.elementRight.style.marginTop = topPosition + 'px';
- },
- /*
- * Method: computePosition
- * Recompute the p(验算)osition of the swipe acording (猛击)to swipeRatio and the size of the map
- */
- computePosition: function() {
- var y = 0;
- var x = this.getSwipeRatio() * (this.map.size.w - this.width);
- return new OpenLayers.Pixel(x, y);
- },
- /*
- * Method: getFirstLayerInLayerSwitcher
- * Get the first layer visible in the layer switcher
- */
- getFirstLayerInLayerSwitcher: function() {
- for (var i = this.map.layers.length - 1; i >= 0; i--) {
- var layer = this.map.layers[i];
- if (layer.displayInLayerSwitcher) {
- return layer;
- }
- }
- return null;
- },
- /*
- * Method: isLayersInLayerSwitcher
- * Check the presence of a layer in the layer switcher
- */
- isLayersInLayerSwitcher: function() {
- for (var i = 0, len = this.map.layers.length; i < len; i++) {
- var layer = this.map.layers[i];
- if (layer.displayInLayerSwitcher) {
- return true;
- }
- }
- return false;
- },
- setSwipeRatio: function(ratio) {
- this.map.events.triggerEvent("changelayer", {
- layer: this.swipeLayer,
- property: "name"
- });
- this.map.swipeRatio = ratio;
- this.map.swipeActive = this.active;
- },
- getSwipeRatio: function() {
- return this.map.swipeRatio;
- },
- /*
- * Method: updateRatio
- * Update the swipeRatio and update the swipe control acc(猛击)ordingly
- */
- updateRatio: function(ratio) {
- this.setSwipeRatio(ratio);
- if (this.isLayersInLayerSwitcher()) {
- this.div.style.display = 'block';
- this.moveTo(this.computePosition());
- this.clipFirstLayer();
- } else {
- this.div.style.display = 'none';
- this.swipeLayer = null;
- }
- },
- CLASS_NAME: "OpenLayers.Control.Swipe(猛击)"
- });
- <pre code_snippet_id="1644580" snippet_file_name="blog_20160413_1_9288680" name="code" class="javascript"><span style="font-family: Arial, Helvetica, sans-serif; rgb(255, 255, 255);">这个js文件里面引用到了一些样式,样式文件的内容如下:</span></pre>
- .olControlSwipe {
- background:url("../img/line.png") repeat;
- display: none;
- }
- .olControlSwipeHover {
- cursor: w-resize;
- }
- .olControlSwipeLayerView {
- background-color: white;
- height: 16px;
- width: 220px;
- margin-top: 23px;
- margin-left: -230px;
- display: block;
- font-size: 11px;
- font-family: Tahoma, Arial;
- font-weight: 700;
- padding-top: 2px;
- background-image: url("../img/bigarrow_left.png");
- background-repeat: no-repeat;
- position: absolute;
- }
- .olControlSwipeLayerSpan {
- visibility: hidden;
- font-size: 11px;
- font-family: Tahoma, Arial;
- font-weight: 700;
- white-space: pre;
- position: absolute;
- }
- .olControlSwipeLayerHide {
- display: none;
- }
- .olControlArrowLeft {
- width: 16px;
- height: 32px;
- margin-left: -1px;
- background-image: url("../img/bigarrow_left.png");
- background-repeat: no-repeat;
- position: absolute;
- }
- .olControlArrowRight {
- width: 16px;
- height: 32px;
- margin-left: 19px;
- background-image: url("../img/bigarrow_right.png");
- background-repeat: no-repeat;
- position: absolute;
- }
最后,调用展示,代用代码如下:
- $("#swipebutton").on("click",function(){
- if(flag){
- swipe.deactiv(猛击)ate(); (无效)
- flag=false;
- }
- else{
- swipe.activate();
- flag=true;
- }
- });