首页 > 解决方案 > 如何集成“搜索 Nominatim 控制”库和 openlayers“测量”示例以同时进行地理编码和测量区域

问题描述

我有一个来自 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>

**second code for measure area:**

  see openlayers example "measure"

**Both the code together:**

    <!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>

标签: javascriptopenlayersnominatim

解决方案


推荐阅读