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---------------------------*/

效果图如下:
在这里插入图片描述
在这里插入图片描述

发布了56 篇原创文章 · 获赞 32 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/hry1243916844/article/details/103937650