1、加载3dTiles
let timeData;
let tileset;
//初始视角定义
const longitude = 116.46;
const latitude = 39.92;
const height = 0;
const rotation = 0;
//加载3dTiles模型
const add3dTiles = () => {
//生成模型进度模拟数据
timeData = createJson();
//时间轴初始化
setClock3dTiles();
//设置模型的矩阵位置--模型带地理位置时无需设置
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(longitude, latitude, height));
Cesium.Matrix4.multiplyByMatrix3(modelMatrix, Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rotation)), modelMatrix);
tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: "/public/model/tileset.json", //需要替换成自己模型的链接
modelMatrix: modelMatrix //模型的矩阵位置,内部无坐标位置的模型(人工模型)使用
}));
//模型着色--根据指定属性着色--DbId属性值需要根据自己模型替换--实现效果如下图片所示
// tileset.style = new Cesium.Cesium3DTileStyle({
// color:{
// conditions:[
// ['${DbId} < 2000', 'color("#ff0000")'],
// ['${DbId} >= 2000 && ${DbId} < 5000', 'rgb(198, 106, 11)'],
// ['${DbId} >= 5000', 'color("#00ff00")'],
// ['true', 'color("#00f")'],
// ]
// }
// })
viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0, -0.5, 0));
//鼠标左键点击事件--获取模型属性信息
// let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// handler.setInputAction((movement) =>{
// let feature = viewer.scene.pick(movement.position);
// if (feature instanceof Cesium.Cesium3DTileFeature) {
// let propertyNames = feature.getPropertyNames(); //获取Cesium3DTileFeature属性
// //遍历获取所有属性名以及其对应的值
// let length = propertyNames.length;
// for (let i = 0; i < length; ++i) {
// let propertyName = propertyNames[i];
// console.log(propertyName + ': ' + feature.getProperty(propertyName));
// }
// }
// }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
2、自定义3dTiles构建数据
interface timeData{
"id": number,
"startTime": number,
"endTime": number,
}
const startTime= 1700186430; //2023-11-17 10:00:30
const endTime= 1700190030; //2023-11-17 11:00:30
//自定义模型结构进度数据--json生成方法
//起止时间:"startTime": 1700186430, ,"endTime": 1700190030,2023-11-17 11:00 30
//起止id: 1-9312,模型数据对应id
const createJson = () => {
const max = 9312; //模型对应最大id
const diffTime = 3600;
let data:Array<timeData> = [];
for(let i=1; i<=max;i++){
const time1 = startTime + getRandomInt(diffTime, 1);
const time2 = startTime + getRandomInt(diffTime, 1);
let start,end;
if(time1 < time2){
start = time1;
end = time2;
}else if(time1 == time2){
start = time1;
end = time1 + 5;
}else{
start = time2;
end = time1;
}
data.push({
"id": i,
"startTime": start,
"endTime": end
})
}
return data;
}
//生成随机数
const getRandomInt = (min:number, max:number) => {
return Math.floor(Math.random() * (max - min)) + min;
}
3、监听时间轴模拟3dTiles构建构成
let vm;
const startDate = '2023-11-17 09:55:00';
const endDate = '2023-11-17 11:03:00';
let proTimeStamp:number = 0;
// 时间轴初始化
const setClock3dTiles = () => {
proTimeStamp = timeToTimestamp(startDate);
let start = Cesium.JulianDate.fromDate(new Date(startDate));//开始时间
start = Cesium.JulianDate.addHours(start, 0, new Cesium.JulianDate());
viewer.clock.currentTime = start.clone();
viewer.clock.canAnimate = true;
viewer.clock.shouldAnimate = true;
viewer.clock.multiplier = 120;
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
let stop = Cesium.JulianDate.fromDate(new Date(endDate));//结束时间
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.timeline.zoomTo(start, stop);
//时间轴监听
getClock3dTiles();
}
//时间轴监听
const clockRelay = (clock:any) =>{
let start = Cesium.JulianDate.addHours(clock.currentTime, 8, new Cesium.JulianDate());
let t = Cesium.JulianDate.toGregorianDate(start)
let currentTime = t.year + "/" + t.month + "/" + t.day + " " + twoDigits(t.hour) + ":" + twoDigits(t.minute) + ":" + twoDigits(t.second);
let curTimeStamp = (timeToTimestamp(currentTime)) / 1000;
if (proTimeStamp == curTimeStamp) {
return;
} else{
proTimeStamp = curTimeStamp;
if(curTimeStamp >= startTime && curTimeStamp <= endTime){
//进行中
vm.curIndex = 1;
vm.diff = curTimeStamp;
}else if(curTimeStamp < startTime){
//未开始
vm.curIndex = 0;
}else{
//已完成
vm.curIndex = 2;
}
}
}
const getClock3dTiles = () => {
viewer.clock.onTick.addEventListener(clockRelay);
};
//日期转时间戳--13位
const timeToTimestamp = (day:string) =>{
let date = new Date(day);
let time = date.getTime();
return time;
};
//如果是一位数,在十位数上补0--时间显示
const twoDigits = (s:number) =>{
if (s < 10)
return "0" + s;
else
return s;
}
4、模型动态着色
//根据状态设置模型样式
//stage--模型构建状态,time--时间轴上对应当前时间戳
const showStatusByStyle = (stage:number,time:number)=>{
let conditions:any = [];
if(stage === 0){
//尚未开始构建模型
conditions = [
["true", "color('#f2f2f2')"]
]
}else if(stage === 2){
//模型构建完成
conditions = [
["true", "color('#00ff00')"]
]
}else{
//模型构建中
timeData.forEach((item:timeData) => {
let temp:Array<string> = [];
if(time < item.startTime){
//未开始
temp = ["(${DbId} === "+ item.id + ") ", "color('#ff0000')"]
}else if(time > item.endTime){
//已完成
temp = ["(${DbId} === "+ item.id + ") ", "color('#00ff00')"]
}else{
//进行中
temp = ["(${DbId} === "+ item.id + ") ", "color('#ffff00')"]
}
conditions.push(temp);
})
}
//给已加载的3dTiles着色
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: conditions
}
})
}
//数据监听--watcher为自定义数据监听类,类似vue wacth,网上实现很多,这里不进行具体阐述
const customWatcher = () => {
vm = new watcher({
data:{
curIndex: -1,
diff: 0
},
watch:{
curIndex(newVal:number,oldVal:number){
//设置模型样式
showStatusByStyle(newVal,0);
},
diff(newVal:number,oldVal:number){
//设置模型样式
showStatusByStyle(1, newVal);
}
}
})
}
4、实现效果
1)模型静态着色
2)模型动态构建过程
欢迎指正与star