Как интегрировать библиотеку «Search Nominatim control» и пример «меры» openlayers для геокодирования и измерения площади одновременно - PullRequest
0 голосов
/ 29 мая 2019

У меня есть код из библиотеки openlayers и пример для измерения длины и площади на карте. У меня также есть код из библиотеки Nominatim для «Поиск элемента управления Nominatim» и геокодирования на карте. Я собрал этот код вместе. Каждый код работает нормально, но он не работает, когда он собирается вместе. Ошибка здесь, после двух щелчков мыши, больше не выбрана точка для измерения длины или площади. Пожалуйста, посоветуйте, какой раздел исправить или изменить. Есть ли более простой способ сделать это? Спасибо

первый код для геокодирования:

<!DOCTYPE html>
<html>
<head>
<!----------------------------------------------------------

    Copyright (c) 2017-2018 Jean-Marc VIGLINO,
    released under CeCILL-B (french BSD like) licence: http://www.cecill.info/

------------------------------------------------------------>
    <title>ol-ext: Search Nominatim control</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <meta name="description" content="Control to add a grid reference to a map." />
    <meta name="keywords" content="ol3, control, search, BAN, french, places, autocomplete" />

    <!-- FontAwesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <!-- jQuery -->
    <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
    <!-- IE 9 bug on ajax tranport  -->
    <!--[if lte IE 9]>
    <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js'></script>
    <![endif]-->

    <!-- Openlayers -->
    <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />
    <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>

    <!-- ol-ext -->
    <link rel="stylesheet" href="http://viglino.github.io/ol-ext/dist/ol-ext.css" />
    <script type="text/javascript" src="http://viglino.github.io/ol-ext/dist/ol-ext.js"></script>

    <link rel="stylesheet" href="../style.css"/>
    <style>
        .ol-search ul {
            color: #333;
            font-size:0.85em;
            max-width: 21em;
        }
        .ol-search ul i {
            display: block;
            color: #333;
            font-size:0.85em;
        }
        .info {
            display: inline-block;
            width: 100%;
        }
        .info a img {
            height: 100px;
            margin-right: .5em;
            float: left;
        }
    </style>
</head>
<body >


    <!-- DIV pour la carte -->
    <div id="map" style="width:50%; height:50%;"></div>

    <div class="options">
        <label>
            <input id="polygon" type="checkbox" onclick="search.set('polygon', $(this).prop('checked')); search.search();" /> 
            extract polygons<br/>(may slow down requests)
        </label>
        <br/>
        <i>Use the search control to start a new search.</i>
    </div>

    <script type="text/javascript">
    // Layers
    var layers = [ new ol.layer.Tile({ source: new ol.source.OSM() }) ];

    // The map
    var map = new ol.Map
        ({  target: 'map',
            view: new ol.View
            ({  zoom: 5,
                center: ol.proj.fromLonLat([51.39, 35.70])
            }),
            interactions: ol.interaction.defaults({ altShiftDragRotate:false, pinchRotate:false }),
            layers: layers
        });

    // Current selection
    var sLayer = new ol.layer.Vector({
        source: new ol.source.Vector(),
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 5,
                stroke: new ol.style.Stroke ({
                    color: 'rgb(255,165,0)',
                    width: 3
                }),
                fill: new ol.style.Fill({
                    color: 'rgba(255,165,0,.3)'
                })
            }),
            stroke: new ol.style.Stroke ({
                color: 'rgb(255,165,0)',
                width: 3
            }),
            fill: new ol.style.Fill({
                color: 'rgba(255,165,0,.3)'
            })
        })
    });
    map.addLayer(sLayer);

    // Set the search control 
    var search = new ol.control.SearchNominatim (
        {   //target: $(".options").get(0),
            polygon: $("#polygon").prop("checked"),
            position: true  // Search, with priority to geo position
        });
    map.addControl (search);

    // Select feature when click on the reference index
    search.on('select', function(e)
        {   // console.log(e);
            sLayer.getSource().clear();
            // Check if we get a geojson to describe the search
            if (e.search.geojson) {
                var format = new ol.format.GeoJSON();
                var f = format.readFeature(e.search.geojson, { dataProjection: "EPSG:4326", featureProjection: map.getView().getProjection() });
                sLayer.getSource().addFeature(f);
                var view = map.getView();
                var resolution = view.getResolutionForExtent(f.getGeometry().getExtent(), map.getSize());
                var zoom = view.getZoomForResolution(resolution);
                var center = ol.extent.getCenter(f.getGeometry().getExtent());
                // redraw before zoom
                setTimeout(function(){
                        view.animate({
                        center: center,
                        zoom: Math.min (zoom, 16)
                    });
                }, 100);
            }
            else {
                map.getView().animate({
                    center:e.coordinate,
                    zoom: Math.max (map.getView().getZoom(),16)
                });
            }
        });

    </script>

</body>
</html>

второй код для области измерения:

см. Пример openlayers "measure"

Оба кода вместе:

<!DOCTYPE html>
<html>
  <head>
    <title>Measure</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css">
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
    <!---------------------------------------
    -----------------------------------------
    -----------------------------------------
    -->
    <!-- FontAwesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <!-- jQuery -->
    <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
    <!-- IE 9 bug on ajax tranport  -->
    <!--[if lte IE 9]>
    <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js'></script>
    <![endif]-->

    <!-- Openlayers -->
     <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />   
    <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>

    <!-- ol-ext -->
    <link rel="stylesheet" href="http://viglino.github.io/ol-ext/dist/ol-ext.css" /> 
    <script type="text/javascript" src="http://viglino.github.io/ol-ext/dist/ol-ext.js"></script>
    <!-- <link rel="stylesheet" href="../style.css"/>  -->
    <style>
            .ol-search ul {
            color: #333;
            font-size:0.85em;
            max-width: 21em;
        }
        .ol-search ul i {
            display: block;
            color: #333;
            font-size:0.85em;
        }
        .info {
            display: inline-block;
            width: 100%;
        }
        .info a img {
            height: 100px;
            margin-right: .5em;
            float: left;
        }
        </style>  
        <!------------------------------
        --------------------------------
        -------------------------------->
    <style>
      .tooltip {
        position: relative;
        background: rgba(0, 0, 0, 0.5);
        border-radius: 4px;
        color: white;
        padding: 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;
      }  
      .map {
        height: 50%;
        width: 70%;
      }   

      </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <form class="form-inline">
      <label>Measure: &nbsp;</label>
      <select id="type">
        <option value="length">Length (LineString)</option>
        <option value="area">Area (Polygon)</option>
      </select>
    </form>
    <script>
      var raster = new ol.layer.Tile({
        source: new ol.source.OSM()
      });

      var source = new ol.source.Vector();

      var vector = new ol.layer.Vector({
        source: source,
        style: new ol.style.Style({
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new ol.style.Stroke({
            color: '#ffcc33',
            width: 2
          }),
          image: new ol.style.Circle({
            radius: 7,
            fill: new ol.style.Fill({
              color: '#ffcc33'
            })
          })
        })
      });


      /**
       * Currently drawn feature.
       * @type {ol.Feature}
       */
      var sketch;


      /**
       * The help tooltip element.
       * @type {Element}
       */
      var helpTooltipElement;


      /**
       * Overlay to show the help messages.
       * @type {ol.Overlay}
       */
      var helpTooltip;


      /**
       * The measure tooltip element.
       * @type {Element}
       */
      var measureTooltipElement;


      /**
       * Overlay to show the measurement.
       * @type {ol.Overlay}
       */
      var measureTooltip;


      /**
       * Message to show when the user is drawing a polygon.
       * @type {string}
       */
      var continuePolygonMsg = 'Click to continue drawing the polygon';


      /**
       * Message to show when the user is drawing a line.
       * @type {string}
       */
      var continueLineMsg = 'Click to continue drawing the line';


      /**
       * Handle pointer move.
       * @param {ol.MapBrowserEvent} evt The event.
       */
      var pointerMoveHandler = function(evt) {
        if (evt.dragging) {
          return;
        }
        /** @type {string} */
        var helpMsg = 'برای اندازه گیری کلیک کنید';

        if (sketch) {
          var geom = (sketch.getGeometry());
          if (geom instanceof ol.geom.Polygon) {
            helpMsg = continuePolygonMsg;
          } else if (geom instanceof ol.geom.LineString) {
            helpMsg = continueLineMsg;
          }
        }

        helpTooltipElement.innerHTML = helpMsg;
        helpTooltip.setPosition(evt.coordinate);

        helpTooltipElement.classList.remove('hidden');
      };


      var map = new ol.Map({
        layers: [raster, vector],
        target: 'map',
        view: new ol.View({
          center: ol.proj.fromLonLat([51.39, 35.70]),
          zoom: 15
        }),
        interactions: ol.interaction.defaults({ altShiftDragRotate:false, pinchRotate:false })
      });

      map.on('pointermove', pointerMoveHandler);

      map.getViewport().addEventListener('mouseout', function() {
        helpTooltipElement.classList.add('hidden');
      });

      var typeSelect = document.getElementById('type');

      var draw; // global so we can remove it later


      /**
       * Format length output.
       * @param {ol.geom.LineString} line The line.
       * @return {string} The formatted length.
       */
      var formatLength = function(line) {
        var length = ol.Sphere.getLength(line);
        var output;
        if (length > 100) {
          output = (Math.round(length / 1000 * 100) / 100) +
              ' ' + 'km';
        } else {
          output = (Math.round(length * 100) / 100) +
              ' ' + 'm';
        }
        return output;
      };


      /**
       * Format area output.
       * @param {ol.geom.Polygon} polygon The polygon.
       * @return {string} Formatted area.
       */
      var formatArea = function(polygon) {
        var area = ol.Sphere.getArea(polygon);
        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;
      };

      function addInteraction() {
        var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString');
        draw = new ol.interaction.Draw({
          source: source,
          type: 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],
              width: 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) {
                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);
              });
            }, this);

        draw.on('drawend',
            function() {
              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);
            }, this);
      }


      /**
       * Creates a new help tooltip
       */
      function createHelpTooltip() {
        if (helpTooltipElement) {
          helpTooltipElement.parentNode.removeChild(helpTooltipElement);
        }
        helpTooltipElement = document.createElement('div');
        helpTooltipElement.className = 'tooltip hidden';
        helpTooltip = new ol.Overlay({
          element: helpTooltipElement,
          offset: [15, 0],
          positioning: 'center-left'
        });
        map.addOverlay(helpTooltip);
      }


      /**
       * Creates a new measure tooltip
       */
      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);
      }


      /**
       * Let user change the geometry type.
       */
      typeSelect.onchange = function() {
        map.removeInteraction(draw);
        addInteraction();
      };

      addInteraction();

      // Current selection
    var sLayer = new ol.layer.Vector({
        source: new ol.source.Vector(),
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 5,
                stroke: new ol.style.Stroke ({
                    color: 'rgb(255,165,0)',
                    width: 3
                }),
                fill: new ol.style.Fill({
                    color: 'rgba(255,165,0,.3)'
                })
            }),
            stroke: new ol.style.Stroke ({
                color: 'rgb(255,165,0)',
                width: 3
            }),
            fill: new ol.style.Fill({
                color: 'rgba(255,165,0,.3)'
            })
        })
    });
    map.addLayer(sLayer);

    // Set the search control 
    var search = new ol.control.SearchNominatim (
        {   //target: $(".options").get(0),
            polygon: $("#polygon").prop("checked"),
            position: true  // Search, with priority to geo position
        });
    map.addControl (search);

    // Select feature when click on the reference index
    search.on('select', function(e)
        {   // console.log(e);
            sLayer.getSource().clear();
            // Check if we get a geojson to describe the search
            if (e.search.geojson) {
                var format = new ol.format.GeoJSON();
                var f = format.readFeature(e.search.geojson, { dataProjection: "EPSG:4326", featureProjection: map.getView().getProjection() });
                sLayer.getSource().addFeature(f);
                var view = map.getView();
                var resolution = view.getResolutionForExtent(f.getGeometry().getExtent(), map.getSize());
                var zoom = view.getZoomForResolution(resolution);
                var center1 = ol.extent.getCenter(f.getGeometry().getExtent());
                // redraw before zoom
                setTimeout(function(){
                        view.animate({
                        center: center1,
                        zoom: Math.min (zoom, 16)
                    });
                }, 100);
            }
            else {
                map.getView().animate({
                    center:e.coordinate,
                    zoom: Math.max (map.getView().getZoom(),16)
                });
            }
        });

    </script>
    <div class="options">
        <label>
            <input id="polygon" type="checkbox" onclick="search.set('polygon', $(this).prop('checked')); search.search();" /> 
            extract polygons<br/>(may slow down requests)
        </label>
        <br/>
        <i>Use the search control to start a new search.</i>
    </div>
  </body>
</html>
...