cesium 3dtile单击选中

监听瓦片加载完成事件,将所有3dtile对象按id归纳到map中

    tileset.readyPromise.then(() => {
        console.log('tileset.readyPromise');
        tileset.setObjsColor()
    })

    // allTilesLoaded 会被调用多次  旋转、放大缩小模型时会触发这个事件,不适合用来做一次性的操作
    // tileset.allTilesLoaded.addEventListener(function() {
    //     console.log('All tiles are loaded');
    //     tileset.setObjsColor()
    // });

 将所有3dtile对象按id归纳到map中的方法

    // 初始化一个map
    Cesium.Cesium3DTileset.MyBuildMap = new Map()
    // 虽然定义的是个体方法,调用也是用个体对象调用,但是evaluateColor方法会执行所有Cesium3DTileset对象
    Cesium.Cesium3DTileset.prototype.setObjsColor = function () {
        let currentStyle = this.style && this.style.style || {};
        this.style = new Cesium.Cesium3DTileStyle({
            ...currentStyle,
            color: {
                evaluateColor: function (feature) {
                    if (!Cesium.Cesium3DTileset.MyBuildMap.has(feature.getProperty('id'))) {
                        Cesium.Cesium3DTileset.MyBuildMap.set(feature.getProperty('id'), [])
                    }
                    if (['gdgdfgdfgf', 'vcxvfg', 'dsfdf1'].includes(feature.getProperty('name'))) {
                        // gdgdfgdfgf a1d0c6e83f027327d8461063f4ac58a6 、vcxvfg 地面
                    } else {
                        Cesium.Cesium3DTileset.MyBuildMap.get(feature.getProperty('id')).push(feature)
                    }
                }
            }
        })
    };

 

点击事件

function myClickEvent(viewer, event) {
    // 500 毫秒内直接返回  防止双击触发2次单击事件
    if (window.selTime && window.selTime > new Date().getTime() - 500) { 
        console.log('500 毫秒内直接返回');
        return
    }
    window.selTime = new Date().getTime()

    // 屏幕坐标转为空间坐标
    let cartesian = getCatesian3FromPX(event.position, viewer);
    // 判断是否定义(是否可以获取到空间坐标)
    if (!Cesium.defined(cartesian)) {
        return
    }
    if (!viewer.selectedEntity) {
        return
    }

    viewer.trackedEntity = undefined
    
    let sel = viewer.selectedEntity
    window.sel = sel

    // pick有id字段时,id存放的是模型对象,也就是viewer.selectedEntity
    // pick有_batchId字段时,pick是Cesium3DTileFeature对象,选中的是3dtile对象,primitive字段存放Cesium3DTileset对象,
    //    此时的viewer.selectedEntity拥有_feature字段,存放的是Cesium3DTileFeature
    //    feature.getProperty('id'), feature.getProperty('name') 也就是 viewer.selectedEntity 的 id name 字段
    const pick = viewer.scene.pick(event.position)
    window.pick = pick

    // 射线选中的一堆对象
    var picks = viewer.scene.drillPick(event.position)
    window.picks = picks

    // 上一个对象 取消选中状态
    if (viewer.oldSel && viewer.oldSel.lcxUnActiveFun) {
        viewer.oldSel.lcxUnActiveFun()
    }

    // 模型对象
    if (sel.lcxActiveFun) {
        console.log('model click');
        sel.lcxActiveFun()
        viewer.oldSel = sel
    } 
    
    // 瓦片模型对象   sel是临时的,增加属性并不会被保存  这里使用pick对象
    else if (pick._batchId != undefined) { // pick._batchId 包含 0 值,会被认为是false,用undefined判断
        console.log('3dtile click', pick.getProperty('id'), pick.getProperty('name'), arr);
        let arr = Cesium.Cesium3DTileset.MyBuildMap.get(pick.getProperty('id'))
        arr.forEach(feature => {
            feature.color = Cesium.Color.YELLOWGREEN
        });
        pick.lcxUnActiveFun = function() {
            arr.forEach(feature => {
                feature.color = Cesium.Color.WHITE
            });
        }
        viewer.oldSel = pick
    }
}

 

这里的瓦片点击事件也可以使用瓦片对象调用setObjsColor方法,这样就不用创建MyBuildMap对象,但是每次都要过滤一遍所有瓦片对象,效率不高,而且有时候会出现setObjsColor方法无限循环的情况,导致页面卡住

    // 瓦片模型对象  这个代码 放在else里执行,只会被执行一次   因为第二次判断sel.lcxActiveFun会为true  sel是临时的,增加属性并不会被保存
    else if (pick._batchId != undefined) { // pick._batchId 包含 0 值,会被认为是false,用undefined判断
        console.log('3dtile click', pick.getProperty('id'), pick.getProperty('name'), arr);
        pick.primitive.setObjsColor([pick.getProperty('id')])
        viewer.oldSel = pick
    }
Cesium.Cesium3DTileset.prototype.setObjsColor = function (ids) {
    let currentStyle = this.style && this.style.style || {};
    this.style = new Cesium.Cesium3DTileStyle({
      ...currentStyle,
      color: {
        evaluateColor: function (feature) {
          console.log(feature.myId, feature._batchId, ids.includes(feature._batchId));
          if (ids.includes(feature._batchId)) {
            return Cesium.Color.RED;
          }
        }
      }
    })
  };

 效果

 

 

 

方案二:

利用单个瓦片加载完成事件,把所有瓦片对象收集到map中

tileset.tileLoad.addEventListener(function(tile: { content: any }) {
  let content = tile.content;
  let featuresLength = content.featuresLength;
  // console.log("要素数量为:", featuresLength, "content", content);
  
  if (featuresLength <= 0) { // Composite3DTileContent 这里面的 _contents 是 Batched3DModel3DTileContent
    for (let child of content._contents) {
      // console.log("要素数量为:", child.featuresLength, "child", child);
      window.tileLoadMap.set(window.tileLoadMap.size + "-child", child)
    }
  } else { // Batched3DModel3DTileContent
    window.tileLoadMap.set(window.tileLoadMap.size + "-root", content)
  }
})

 

把所有相同名称的瓦片放到同一个key中(第一次点击时触发)

function init3DTileFeatureMap() {
  window.featureMap = new Map()
  for (let key of window.tileLoadMap.keys()) {
    let content = window.tileLoadMap.get(key)
    let featuresLength = content.featuresLength
    for (let i = 0; i < featuresLength; i++) {
      let feature = content.getFeature(i)
      feature.myId = key + "-" + i
      let arr = window.featureMap.get(feature.getProperty('id')) || []
      arr.push(feature)
      window.featureMap.set(feature.getProperty('id'), arr)
    }
  }
}

 

点击事件

handler.setInputAction(function (event) {
  const feature = viewer.scene.pick(event.position);
  window.pick = feature
  if (!Cesium.defined(feature) || !(feature instanceof Cesium.Cesium3DTileFeature)) {
    return;
  }
  if (!feature.myId) { // 没有myId,说明没有初始化过,表示这是第一次点击
    init3DTileFeatureMap()
  }
  if (feature.getProperty('name') == 'pasted__polySurface292') { // 地面
    return;
  }
  if (window.oldFeatureId) {
    let featureArr = window.featureMap.get(window.oldFeatureId)
    for (let item of featureArr) {
      item.color = new Cesium.Color(1, 1, 1, 1)
    }
  }
  window.oldFeatureId = feature.getProperty('id')
  let featureArr = window.featureMap.get(feature.getProperty('id'))
  console.log(feature.getProperty('id'), feature.getProperty('name'), '瓦片数:', featureArr.length);
  
  for (let item of featureArr) {
    item.color = Cesium.Color.fromCssColorString('#00FF00')
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)

 

posted @ 2023-10-24 13:59  1156740846  阅读(731)  评论(0编辑  收藏  举报