cesium查詢arcgis/wms服務並實現自定義信息框,分頁展示查詢要素

想實現自定義信息框,首先要在cesium初始化時,將默認的infoBox設置爲false,因此要自己手動實現查詢功能。
1. 監聽點擊事件,對arcgis/wms服務進行查詢
具體實現代碼如下:

   const _self = this;
   const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (movement) {
      const ray = viewer.camera.getPickRay(movement.position);
      const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
      if (cartesian) {
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        if (cartographic) {
          var xy = new Cesium.Cartesian2();
          var alti = viewer.camera.positionCartographic.height;
          var level = getLevel(alti);
          if (imageryProvider.ready) {
            xy = imageryProvider.tilingScheme.positionToTileXY(cartographic, level, xy);
            var promise = imageryProvider.pickFeatures(xy.x, xy.y, level, cartographic.longitude, cartographic.latitude);
            Cesium.when(promise, function (data) {
              if (layerInfo && layerInfo.length > 0) {
                //這裏就得到了查詢結果
                _self.renderPopup(layerInfo, movement.position)
              }
            });
          }
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

這裏主要使用了pickFeatures接口,ArcGisMapServerImageryProvider和WebMapServiceImageryProvider都有這個接口。
接口需要瓦片座標和地理座標以及當前瓦片等級level參數。
瓦片座標通過WebMapServiceImageryProvider對象的tilingScheme屬性中的positionToTileXY接口獲取;
這裏需要點擊處地理座標和瓦片等級level,看來level參數很重要,查看api,竟然麼有發現獲取level的接口,心想level和相機高度一一對應,於是自己就逐級縮放,測試出一組參數(可能有些不準確):
原文在這裏

  getLevel(height) {
    if (height > 48000000) {
      return 0;
    } else if (height > 24000000) {
      return 1;
    } else if (height > 12000000) {
      return 2;
    } else if (height > 6000000) {
      return 3;
    } else if (height > 3000000) {
      return 4;
    } else if (height > 1500000) {
      return 5;
    } else if (height > 750000) {
      return 6;
    } else if (height > 375000) {
      return 7;
    } else if (height > 187500) {
      return 8;
    } else if (height > 93750) {
      return 9;
    } else if (height > 46875) {
      return 10;
    } else if (height > 23437.5) {
      return 11;
    } else if (height > 11718.75) {
      return 12;
    } else if (height > 5859.38) {
      return 13;
    } else if (height > 2929.69) {
      return 14;
    } else if (height > 1464.84) {
      return 15;
    } else if (height > 732.42) {
      return 16;
    } else if (height > 366.21) {
      return 17;
    } else {
      return 18;
    }
  },

最後就是獲取查詢結果,pickFeatures接口是異步的,我們使用promise獲取。
2.自定義信息框,分頁展示
因爲arcgis服務點擊查到的要素可能爲多個,所以應分頁展示查到的結果。
renderPopup函數主要是將查詢到的結果處理成一個contentArr 數組,方便點擊頁碼更換內容。

 renderPopup = (layerInfo, position) => {
    const { viewer, handler } = this.props;
    let contentArr = [];
    let page = '';
    for (let i = 0; i < layerInfo.length; i++) {
      // 處理查詢到的結果
      const data = layerInfo[i].data;
      const content = `<div>${data.attributes.OBJNAME}</div><table><tbody>
          <tr><td>FID:</th><td>${data.attributes.FID}</td></tr>
          <tr><td>名稱:</th><td>${data.attributes.OBJNAME}</td></tr>
          <tr><td>狀態:</th><td>${data.attributes.OBJSTATE}</td></tr>
          <tr><td>地址:</th><td>${data.attributes.DEPTNAME1}</td></tr>
          </tbody></table>`;
      contentArr.push(content)
      // 生成頁碼
      if (i == 0) {
        page = page + `<li style="color: #fff000; border: 1px solid #fff000;" id=${i}>${i + 1}</li>`
      } else {
        page = page + `<li id=${i}>${i + 1}</li>`
      }
    }
    let pageContent = `<ul id="page">${page}</ul>`
    this.infoPopuEvent(handler, position, contentArr, pageContent)
  }

infoPopuEvent函數主要實現了自定義的彈窗:

  infoPopuEvent = (handler, position, contentArr, pageContent) => {
    const infoDiv = `<div id="trackPopUp" class="trackPopUp">
                      <div id="trackPopUpContent" class="leaflet-popup" style="top:5px;left:0;">
                        <a class="leaflet-popup-close-button" href="#">×</a>
                        <div class="leaflet-popup-content-wrapper">
                          <div id="trackPopUpLink" class="leaflet-popup-content">                        
                          </div>
                          <div class="leaf-popup-page">${pageContent}</div>
                        </div>
                      </div>
                  </div>`;
    if ($("#trackPopUp").length > 0) {
      $('#trackPopUp').remove();
    }
    $('#cesiumContainer').append(infoDiv);
    $('#trackPopUp').show();
    //頁碼點擊事件
    $('#page li').click(e => {
      const index = parseInt(e.currentTarget.id)
      const liChild = $('#page').children();
      $(liChild[index]).css({ "color": "#fff000", "border": "1px solid #fff000" })
      $(liChild[index]).siblings().css({ "color": "#fff", "border": "1px solid #fff" })
      $('#trackPopUpLink').empty();
      $('#trackPopUpLink').append(contentArr[index]);
    })
    var obj = { position: position, content: contentArr[0] };
    infoWindow(obj);
    function infoWindow(obj) {
      $('.cesium-selection-wrapper').show();
      $('#trackPopUpLink').empty();
      $('#trackPopUpLink').append(obj.content);
      function positionPopUp(c) {
        var x = c.x - ($('#trackPopUpContent').width()) / 2;
        var y = c.y - ($('#trackPopUpContent').height());
        $('#trackPopUpContent').css('transform', 'translate3d(' + x + 'px, ' + y + 'px, 0)');
      }
      var c = new Cesium.Cartesian2(obj.position.x, obj.position.y);
      $('#trackPopUp').show();
      positionPopUp(c);
      $('.leaflet-popup-close-button').click(function () {
        $('#trackPopUp').hide();
        $('#trackPopUpLink').empty();
        $('.cesium-selection-wrapper').hide();
        return false;
      });
    //綁定地圖移動
    handler.setInputAction(function (movement) {
      $('#trackPopUp').hide();
    }, Cesium.ScreenSpaceEventType.LEFT_UP);
    //綁定地圖縮放
    handler.setInputAction(function (movement) {
      $('#trackPopUp').hide();
    }, Cesium.ScreenSpaceEventType.WHEEL);
    //綁定滾輪點擊事件
    handler.setInputAction(function (movement) {
      $('#trackPopUp').hide();
    }, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);
  },

css代碼:

/*--------------------------氣泡彈窗Start---------------------------*/

.trackPopUp {
    display: none;
    color: rgb(255, 255, 255);
}

.leaflet-popup {
    position: absolute;
    z-index: 100;
}

.leaflet-popup-close-button {
    position: absolute;
    top: 0;
    right: 0;
    padding: 4px 4px 0 0;
    text-align: center;
    font: 25px/25px Tahoma, Verdana, sans-serif;
    color: rgb(255, 255, 255);
    text-decoration: none;
    font-weight: bold;
    background: transparent;
}

.leaflet-popup-content-wrapper {
    max-height: 500px;
    overflow-y: auto;
    min-height: 180px;
    width: 300px;
    padding: 1px;
    text-align: left;
    border-radius: 5px;
    background-color: #002445;
}

.leaflet-popup-content {
    margin: 5px 20px;
    line-height: 1.4;
}

.leaf-popup-page {
    position: absolute;
    right: 0;
    bottom: 0;
}

.leaf-popup-page ul li {
    margin: 3px;
    width: 20px;
    height: 20px;
    text-align: center;
    border: 1px solid #fff;
    text-decoration: none;
    list-style:none;
    float: left;![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200111162952596.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hyeTEyNDM5MTY4NDQ=,size_16,color_FFFFFF,t_70)
}

.leaf-popup-page ul li:hover {
    color: #fff000;
    border: 1px solid #fff000;
    cursor: pointer;
}

.leaflet-popup-content div {
    text-align: center;
    font-size: 18px;
}

.leaflet-popup-content table {
    margin-top: 15px;
}

.leaflet-popup-content table tr {
    height: 25px;
}

/*--------------------------氣泡彈窗END---------------------------*/

效果圖如下:
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章