实现思路主要是通过 Knockout 实现了对输入值的监听,当输入值发生变化时,分别执行不同的操作来实现模型的变换
参考沙盒案例:3D Tiles Adjust Height - Cesium Sandcastle
<!--
* @Description:
* @Author: yiyi
* @Date: 2023-12-14 16:19:44
* @LastEditTime: 2024-01-05 10:06:27
* @LastEditors: yiyi
* 加油搞起来
-->
<template>
<div id="cesiumContainer"></div>
<div id="toolbar" ref="toolbar" style="position: absolute;left: 0;
top: 0;z-index: 99;background-color: #fff;width: 500px;">
<div>Scale</div>
<a-row>
<a-col :span="12">
<a-slider v-model:value="inputValue.scale" :min="0" :max="10" :step="1" @change="changeScale" />
</a-col>
<a-col :span="4">
<a-input-number v-model:value="inputValue.scale" :min="0" :max="10" :step="1" style="margin-left: 16px" />
</a-col>
</a-row>
<div>Height-offset</div>
<a-row>
<a-col :span="12">
<a-slider v-model:value="inputValue.height" :min="0" :max="10" :step="1" @change="changeRotateH" />
</a-col>
<a-col :span="4">
<a-input-number v-model:value="inputValue.height" :min="0" :max="10" :step="1" style="margin-left: 16px" />
</a-col>
</a-row>
<div>RotateX</div>
<a-row>
<a-col :span="12">
<a-slider v-model:value="inputValue.RotateX" :min="0" :max="10" :step="1" @change="changeRotateX" />
</a-col>
<a-col :span="4">
<a-input-number v-model:value="inputValue.RotateX" :min="0" :max="10" :step="1" style="margin-left: 16px" />
</a-col>
</a-row>
<div>RotateY</div>
<a-row>
<a-col :span="12">
<a-slider v-model:value="inputValue.RotateY" :min="0" :max="10" :step="1" @change="changeRotateY" />
</a-col>
<a-col :span="4">
<a-input-number v-model:value="inputValue.RotateY" :min="0" :max="10" :step="1" style="margin-left: 16px" />
</a-col>
</a-row>
<div>RotateZ</div>
<a-row>
<a-col :span="12">
<a-slider v-model:value="inputValue.RotateZ" :min="0" :max="10" :step="1" @change="changeRotateZ" />
</a-col>
<a-col :span="4">
<a-input-number v-model:value="inputValue.RotateZ" :min="0" :max="10" :step="1" style="margin-left: 16px" />
</a-col>
</a-row>
</div>
</template>
<script setup>
import { onMounted, reactive, ref, toRaw } from 'vue';
import * as Cesium from 'cesium';
import { RotateZ, RotateY, RotateX, RotateH } from './utils/move';
const inputValue = reactive({
scale: 0,
height: 0,
RotateX: 0,
RotateY: 0,
RotateZ: 0
});
const toolbar = ref(null);
let viewer, tileset, m;
onMounted(() => {
// cesium 初始化
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDJiYWZjNy01YWIzLTQ5MDQtOWRjMC1lNzRjMzZlNDkxZjgiLCJpZCI6MTYzNzI4LCJpYXQiOjE2OTM0NzM4NTZ9.TZLI1V4-2pYZoVSbt-zOkV7Yx7elhjAsqfFt5h4Nrlk';
//加载影像图层
const esri = new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
enablePickFeatures: false,
layer: "img",
style: "default",
tileMatrixSetID: "w",
format: "tiles",
maximumLevel: 18,
});
window.viewer = viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true,
requestWaterMask: true
}),
imageryProvider: esri,
shouldAnimate: true, //是否允许动画
selectionIndicator: false,
baseLayerPicker: false,
fullscreenButton: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
showRenderLoopErrors: false,
shadows: false,
});
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true;
viewer._cesiumWidget._creditContainer.style.display = "none"; //去除版权信息
viewer.scene.globe.depthTestAgainstTerrain = true;
const origin = Cesium.Cartesian3.fromDegrees(117.22089726144343, 31.833569328835598, 60);
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
window.tileset = tileset = viewer.scene.primitives.add(
Cesium.Model.fromGltf({
id: 'site', // 模型id
position: origin, // 模型位置
url: '../public/Cesium_Air.glb',
show: true, // default
scale: 2.0, // double size
maximumScale: 20000, // never larger than 20000 * model size (overrides minimumPixelSize)
allowPicking: true,
modelMatrix: modelMatrix,
minimumPixelSize: 128,//最小像素大小,可以避免太小看不见
})
);
m = tileset.modelMatrix;
tileset.readyPromise.then(function (e) {
var boundingSphere = tileset.boundingSphere;
viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius * 2));
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
});
Cesium.knockout.applyBindings(inputValue, toolbar.value);
});
const changeRotateZ = (v) => {
RotateZ(v, m);
};
const changeRotateY = (v) => {
RotateY(v, m);
};
const changeRotateX = (v) => {
RotateX(v, m);
};
const changeRotateH = (v) => {
RotateH(v, m);
};
const changeScale = (v) => {
tileset.scale = v;
};
</script>
<style scoped>
#cesiumContainer {
width: 100%;
height: 100%;
}
#cesiumContainer .cesium-viewer-bottom {
display: none;
}
.floorSingle {
position: absolute;
z-index: 99;
left: 0px;
top: 30px;
background-color: aliceblue;
}
.ant-select {
position: absolute;
z-index: 99;
left: 0px;
top: 30px;
}
</style>