监听瓦片加载完成事件,将所有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)