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)