• OpenLayer 学习之自定义测量控件(目前ol3的版本不会抛异常)


    一、自定义控件是在继承基类空间基础上实现的,控件不是我写的(毕竟技术有限)最近也在一直在研究源码进行模仿想写出自己的功能更为强大的控件。

    二、控件源码

    1、css样式设置

    .tooltip {
      position: relative;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 4px;
      color: white;
      padding: 4px 24px 4px 8px;
      opacity: 0.7;
      white-space: nowrap;
    }
    .tooltip-measure {
      opacity: 1;
      font-weight: bold;
    }
    .tooltip-static {
      background-color: #ffcc33;
      color: black;
      border: 1px solid white;
    }
    .tooltip-measure:before,
    .tooltip-static:before {
      border-top: 6px solid rgba(0, 0, 0, 0.5);
      border-right: 6px solid transparent;
      border-left: 6px solid transparent;
      content: "";
      position: absolute;
      bottom: -6px;
      margin-left: -7px;
      left: 50%;
    }
    .tooltip-static:before {
      border-top-color: #ffcc33;
    }
    .ol-popup-closer {
        text-decoration: none;
        position: absolute;
        top: 4px;
        right: 8px;
        color: red;
    }
    .ol-popup-closer:after {
        content: "✖";
    }
    /*MeasureTool*/
    
    .MeasureTool{
      position: absolute;
      top: 2.0em;
      right: 5em;
      text-align: left;
      padding: 0;
    }
    .MeasureTool .ulbody{
      display: none;
    }
    .MeasureTool.shown .ulbody{
      display: block;
    }
    .ulbody li input:focus, .ulbody li input:hover {
      background-color: white;
      color: blue;
      font-weight: bold;
    }
    .MeasureTool ul {
      padding: 0;
      list-style: none;
      margin: 0;
    }
    .MeasureTool ul li{
      text-align: center;
    }
    .MeasureTool>ul>li>input{
      background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABiUlEQVRIS8WUQU7CQBSG/ze6lxsoJxCPYMpePIG4almJW2giJq1xJ6ykbuAG6p6GIwgnkBsYtwb7zGsZLKUk0tI4m6btzP/N/+bNTyh4UMH6+D+A7fkdACwOHdO4TTq1vVENoGP9PW2O/NvowPb8UDwafO6Y1Zc4xO77ExDigFStvwEYPccymhrQGYxL86/gIw50TCM7gBkz1zLKWrD16NeVwgCMqXaRGcDgTwIdzANVvm+czgTS9kZDAl0AkLO5WZxTNgfM/EpEZwxcu6bRjQD+jIDDgNSJ4uAtFyAIcCnlEJBrVWutp3FFRMWZa1ZLuhkyl0hKs6+Cd73Ltuc3CXjQwNwA2ZkuibQrM+pSMnF21zCGOwHYfb8LwhUYPSauxw99N4Do1j7/3jtMHcuoyHsegESFxET4lN7Hnpoo/j6Kvkc3exEpy3nJSCk+7OKhtinYton0pB6thlooFZYkx1hZnwbIob2+NA2wlv1bEsNs0kMAK5Z012wpupye1Cu+i7Lu9K/rCnfwA90A1i8VnCB2AAAAAElFTkSuQmCC') /*logo.png*/;
      background-position: center center;
      background-repeat: no-repeat;
    }
    .MeasureTool input[type="button"]{
      background-color: rgba(255, 255, 255, 0.4);
       60px;
      height: 26px;
      border: 0;
    }
    .MeasureTool .ulbody li{
      border-top: 1px solid rgba(221, 221, 221, 0.4);
    }
    

    2、JS源码

    /**
     * OpenLayers 3 MeasureTool Control.
     * See [the examples](./examples) for usage.
     * @constructor
     * @extends {ol.control.Control}
     * @param {Object} opt_options Control options, extends olx.control.ControlOptions adding:
     *                              **`tipLabel`** `String` - the button tooltip.
     */
    //构造函数
    ol.control.MeasureTool = function(opt_options) {
    
      var options = opt_options || {};
    
      this.sphereradius = options.sphereradius ?
        options.sphereradius : 6378137;
    
      this.mapListeners = [];
    
      // hiddenclass
      this.hiddenClassName = 'ol-control MeasureTool';
      if (ol.control.MeasureTool.isTouchDevice_()) {
          this.hiddenClassName += ' touch';
      }
      // shownClass
      this.shownClassName = this.hiddenClassName + ' shown';
    
      var element = document.createElement('div');
      element.className = this.hiddenClassName;
    
      this.panel = document.createElement('ul');
      element.appendChild(this.panel);
    
      var ulheader = document.createElement('li');
      this.panel.appendChild(ulheader);
    
      var inputMeasure = document.createElement('input');
      inputMeasure.type = "button";
      ulheader.appendChild(inputMeasure);
    
      var ulbody = document.createElement('li');
      this.panel.appendChild(ulbody);
    
      var html = '';
      html += '<ul class="ulbody">';
      html += '<li><input type="button" value="Line"></li>';
      html += '<li><input type="button" value="Area"></li>';
      html += '<li><input type="checkbox" value="no"></li>';
      html += '</ul>';
      ulbody.innerHTML = html;
    
      var this_ = this;
    
      inputMeasure.onmouseover = function(e) {
        this_.showPanel();
      };
      inputMeasure.onclick = function(e) {
          e = e || window.event;
          this_.showPanel();
          e.preventDefault();
      };
    
      var lis = ulbody.getElementsByTagName("li");
    
      this.sourceMesure = new ol.source.Vector();
      this.vectorMesure = new ol.layer.Vector({
          source: this.sourceMesure,
        style: new ol.style.Style({
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new ol.style.Stroke({
            color: '#ffcc33',
             2
          }),
          image: new ol.style.Circle({
            radius: 7,
            fill: new ol.style.Fill({
              color: '#ffcc33'
            })
          })
        })
      });
    
      //type length or area
      var typeSelect={};
      //Line start
      lis[0].onclick = function(e) {
        typeSelect.value = 'length';
        typeSelect.check = lis[2].getElementsByTagName("input")[0].checked;
        this_.mapmeasure(typeSelect);
      };
      //Area start
      lis[1].onclick = function(e) {
        typeSelect.value = 'area';
        typeSelect.check = lis[2].getElementsByTagName("input")[0].checked;
        this_.mapmeasure(typeSelect);
      };
    
      this_.panel.onmouseout = function(e) {
          e = e || window.event;
          if (!this_.panel.contains(e.toElement || e.relatedTarget)) {
              this_.hidePanel();
          }
      };
    
      ol.control.Control.call(this, {
          element: element,
      });
    
    };
    //继承
    ol.inherits(ol.control.MeasureTool, ol.control.Control);
    
    ol.control.MeasureTool.prototype.mapmeasure = function(typeSelect) {
        var source = this.sourceMesure;
        var vector = this.vectorMesure;
      var wgs84Sphere = new ol.Sphere(this.sphereradius);
    
      var sketch;
      var helpTooltipElement;
      var measureTooltipElement;
      var measureTooltip;
    
      var map = this.getMap();
      map.addLayer(vector);
    
      map.getViewport().addEventListener('mouseout', function() {
        helpTooltipElement.classList.add('hidden');
      });
    
      var draw; // global so we can remove it later
    
      var formatLength = function(line) {
        var length;
        if (typeSelect.check) {
          var coordinates = line.getCoordinates();
          length = 0;
          var sourceProj = map.getView().getProjection();
          for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
            var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');
            var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');
            length += wgs84Sphere.haversineDistance(c1, c2);
          }
        } else {
          var sourceProj = map.getView().getProjection();
          var geom = /** @type {ol.geom.Polygon} */(line.clone().transform(
              sourceProj, 'EPSG:3857'));
          length = Math.round(geom.getLength() * 100) / 100;
          // length = Math.round(line.getLength() * 100) / 100;
        }
        var output;
        if (length > 100) {
          output = (Math.round(length / 1000 * 100) / 100) +
              ' ' + 'km';
        } else {
          output = (Math.round(length * 100) / 100) +
              ' ' + 'm';
        }
        return output;
      };
    
      var formatArea = function(polygon) {
        if (typeSelect.check) {
          var sourceProj = map.getView().getProjection();
          var geom = /** @type {ol.geom.Polygon} */(polygon.clone().transform(
              sourceProj, 'EPSG:4326'));
          var coordinates = geom.getLinearRing(0).getCoordinates();
          area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
        } else {
          var sourceProj = map.getView().getProjection();
          var geom = /** @type {ol.geom.Polygon} */(polygon.clone().transform(
              sourceProj, 'EPSG:3857'));
          area = geom.getArea();
          // area = polygon.getArea();
        }
        var output;
        if (area > 10000) {
          output = (Math.round(area / 1000000 * 100) / 100) +
              ' ' + 'km<sup>2</sup>';
        } else {
          output = (Math.round(area * 100) / 100) +
              ' ' + 'm<sup>2</sup>';
        }
        return output;
      };
    
      var popupcloser = document.createElement('a');
      popupcloser.href = 'javascript:void(0);';
      popupcloser.classList.add('ol-popup-closer');
    
      function addInteraction() {
        var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString');
        draw = new ol.interaction.Draw({
          source: source,
          type: /** @type {ol.geom.GeometryType} */ (type),
          style: new ol.style.Style({
            fill: new ol.style.Fill({
              color: 'rgba(255, 255, 255, 0.2)'
            }),
            stroke: new ol.style.Stroke({
              color: 'rgba(0, 0, 0, 0.5)',
              lineDash: [10, 10],
               2
            }),
            image: new ol.style.Circle({
              radius: 5,
              stroke: new ol.style.Stroke({
                color: 'rgba(0, 0, 0, 0.7)'
              }),
              fill: new ol.style.Fill({
                color: 'rgba(255, 255, 255, 0.2)'
              })
            })
          })
        });
        map.addInteraction(draw);
    
        createMeasureTooltip();
        createHelpTooltip();
    
        var listener;
        draw.on('drawstart',
          function(evt) {
            // set sketch
            sketch = evt.feature;
    
            /** @type {ol.Coordinate|undefined} */
            var tooltipCoord = evt.coordinate;
    
            listener = sketch.getGeometry().on('change', function(evt) {
              try {
                var geom = evt.target;
                var output;
                if (geom instanceof ol.geom.Polygon) {
                  output = formatArea(geom);
                  tooltipCoord = geom.getInteriorPoint().getCoordinates();
                } else if (geom instanceof ol.geom.LineString) {
                  output = formatLength(geom);
                  tooltipCoord = geom.getLastCoordinate();
                }
                measureTooltipElement.innerHTML = output;
                measureTooltip.setPosition(tooltipCoord);
              } catch (e) {
                map.removeInteraction(draw);
              } finally {
              }
    
            });
          }, this);
    
        draw.on('drawend',
            function() {
              measureTooltipElement.appendChild(popupcloser);
              measureTooltipElement.className = 'tooltip tooltip-static';
              measureTooltip.setOffset([0, -7]);
              // unset sketch
              sketch = null;
              // unset tooltip so that a new one can be created
              measureTooltipElement = null;
              createMeasureTooltip();
              ol.Observable.unByKey(listener);
              //end
              map.removeInteraction(draw);
              // map.getInteractions().item(1).setActive(false);
            }, this);
      }
    
      function createHelpTooltip() {
        if (helpTooltipElement) {
          helpTooltipElement.parentNode.removeChild(helpTooltipElement);
        }
        helpTooltipElement = document.createElement('div');
        helpTooltipElement.className = 'tooltip hidden';
      }
      function createMeasureTooltip() {
        if (measureTooltipElement) {
          measureTooltipElement.parentNode.removeChild(measureTooltipElement);
        }
        measureTooltipElement = document.createElement('div');
        measureTooltipElement.className = 'tooltip tooltip-measure';
        measureTooltip = new ol.Overlay({
          element: measureTooltipElement,
          offset: [0, -15],
          positioning: 'bottom-center'
        });
        map.addOverlay(measureTooltip);
      }
    
      //clear
      popupcloser.onclick = function(e) {
        map.getOverlays().clear();
        vector.getSource().clear();
        // map.removeLayer(vector);
      };
    
      addInteraction();
    };
    
    /**
     * Show the MeasureTool.
     */
    ol.control.MeasureTool.prototype.showPanel = function() {
        if (this.element.className != this.shownClassName) {
            this.element.className = this.shownClassName;
        }
    };
    
    /**
     * Hide the MeasureTool.
     */
    ol.control.MeasureTool.prototype.hidePanel = function() {
        if (this.element.className != this.hiddenClassName) {
            this.element.className = this.hiddenClassName;
        }
    };
    
    /**
     * Set the map instance the control is associated with.
     * @param {ol.Map} map The map instance.
     */
    ol.control.MeasureTool.prototype.setMap = function(map) {
        // Clean up listeners associated with the previous map
        for (var i = 0, key; i < this.mapListeners.length; i++) {
            this.getMap().unByKey(this.mapListeners[i]);
        }
        this.mapListeners.length = 0;
        // Wire up listeners etc. and store reference to new map
        ol.control.Control.prototype.setMap.call(this, map);
        if (map) {
            var this_ = this;
            this.mapListeners.push(map.on('pointerdown', function() {
                this_.hidePanel();
            }));
        }
    };
    
    /**
     * Generate a UUID
     * @returns {String} UUID
     *
     * Adapted from http://stackoverflow.com/a/2117523/526860
     */
    ol.control.MeasureTool.uuid = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    }
    
    /**
    * @private
    * @desc Apply workaround to enable scrolling of overflowing content within an
    * element. Adapted from https://gist.github.com/chrismbarr/4107472
    */
    ol.control.MeasureTool.enableTouchScroll_ = function(elm) {
       if(ol.control.MeasureTool.isTouchDevice_()){
           var scrollStartPos = 0;
           elm.addEventListener("touchstart", function(event) {
               scrollStartPos = this.scrollTop + event.touches[0].pageY;
           }, false);
           elm.addEventListener("touchmove", function(event) {
               this.scrollTop = scrollStartPos - event.touches[0].pageY;
           }, false);
       }
    };
    
    /**
     * @private
     * @desc Determine if the current browser supports touch events. Adapted from
     * https://gist.github.com/chrismbarr/4107472
     */
    ol.control.MeasureTool.isTouchDevice_ = function() {
        try {
            document.createEvent("TouchEvent");
            return true;
        } catch(e) {
            return false;
        }
    };
    

    三、使用控件

    1、js控件引入

     <script src="ol3-measuretool-master/measuretool.js"></script>

    2、声明控件

     new ol.control.MeasureTool( {sphereradius : 6378137}),

    其中的参数sphereradius 是用来支持geodesic测量设置球体半径的,可根据不同的模型设置不同的半径大小,默认大小为6378137,在引入时也可以不传入该参数。

    NOTE:测量工具中的checkbox选中为使用geodesic测量,未选中为不使用geodesic测量,默认为未选中。

    四、总结

    通过这几天的研究我发现如果要实现自定义控件,里面有部分函数我们不需要改动,在构造函数那一部分我们需要创建自己定义的标签,其他后面最后的几个函数是不需要改动的,待下次继续完善

  • 相关阅读:
    Shell for
    rsync 目录 斜杠
    shell local
    linux secureCRT utf-8编码显示
    eclipse maven 项目不显示 target目录
    如何打印身份证实际大小
    linux 去掉 ^M
    hibernate 之 集合映射中list映射
    hibernate 之 复合主键映射
    hibernate 之 组件映射
  • 原文地址:https://www.cnblogs.com/tuboshu/p/10752365.html
Copyright © 2020-2023  润新知