token记得换成您自己的!!!
申请cesium的token 官网【Cesium: The Platform for 3D Geospatial】
pickEllipsoid在加载地形的情况下有一定误差,地形凹凸程度越大,误差越大。
pickPosition在depthTestAgainstTerrain = false时只能在3DTile上获取准确位置,当depthTestAgainstTerrain = true时, 在3DTile和底图上均能获取准确位置
viewer.scene.globe.depthTestAgainstTerrain = true; // 开启地形深度检测
// pickEllipsoid在加载地形的情况下有一定误差,地形凹凸程度越大,误差越大。
// pickPosition在depthTestAgainstTerrain = false时只能在3DTile上获取准确位置,当depthTestAgainstTerrain = true时,
// 在3DTile和底图上均能获取准确位置
<template>
<div id="cesiumContainer"></div>
<!-- <div id="infoboxs" :style="qnameclass" class="qnamebox">{{ qname }}</div> -->
<!-- <div class="btnbox">
<div class="btnboxel">
<el-button class="btnel" v-for="item in pointData2" :key="item.modelId" @click="showBubble(item)">{{ item.name
}}</el-button>
</div>
</div> -->
</template>
<script setup lang='ts'>
import * as Cesium from "cesium";
import $ from 'jquery'
import { fa } from "element-plus/es/locales.mjs";
import { onMounted, reactive, ref, computed, nextTick } from "vue";
import { it } from "node:test";
// 地图实例
let viewer: any;
let tileset; //设置一个变量来存放通过3DTiles创建的模型
let handler
let selectedFeature
const selected = {
feature: undefined,
originalColor: new Cesium.Color(),
};
let qname = ref()
let qnameclass = reactive({
top: '',
left: '',
})
let valshow
let infos: any = reactive({
pups: []
})
let infoBox1 = ref()
onMounted(() => {
// 初始化Cesium并创建viewer
Cesium.Ion.defaultAccessToken =
"换成自己的token";
viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: true, // 禁用沙箱,解决控制台报错
selectionIndicator: false, //选择指示器
timeline: false, // 时间轴
animation: false, // 动画小组件
// geocoder: false, // 地理编码(搜索)组件
homeButton: false, // 首页,点击之后将视图跳转到默认视角
sceneModePicker: false, // 投影方式,切换2D、3D 和 Columbus View (CV) 模式。
baseLayerPicker: false, // 底图组件,选择三维数字地球的底图(imagery and terrain)。
navigationHelpButton: false, // 帮助按钮
fullscreenButton: false, // 全屏按钮
imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
// enablePickFeatures: false,
}),
// terrainProvider: new Cesium.CesiumTerrainProvider({
// url: "http://data.marsgis.cn/terrain",
// }),
scene3DOnly: true, // 每个几何实例将只能以3D渲染以节省GPU内存
sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneMode
});
viewer.imageryLayers.addImageryProvider(
new Cesium.WebMapTileServiceImageryProvider({
url: "http://t0.tianditu.gov.cn/cia_w/wmts?tk=2d58d1852b0b28db058bbe353a22b91b",
layer: "cia",
style: "default",
tileMatrixSetID: "w",
format: "tiles",
maximumLevel: 18,
})
);
viewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏logo版权
viewer.scene.globe.depthTestAgainstTerrain = true; // 开启地形深度检测
let destination = Cesium.Cartesian3.fromDegrees(117.598276295, 24.21475226, 80); // 北京天安门广场的经纬度坐标及高度
viewer.camera.flyTo({
destination: destination,
duration: 2, // 飞行动画持续时间(单位:秒)
orientation: {
heading: Cesium.Math.toRadians(-25), // 方向 y 左右摇头
pitch: Cesium.Math.toRadians(-20), // 倾斜角度 x 上下点头 -90看地面 0看前方 90看天上
roll: 0, //z 歪头看
}
});
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// getasdM()
// const layer = viewer.imageryLayers.get(0);
// viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.0, 0.0, 0); // 把地球背景色透明
// layer.alpha = 0.8;
// viewer.scene.globe.translucency.backFaceAlpha = 0.5; // 应用于地球背面的恒定半透明度
// viewer.scene.globe.translucency.enabled = true; // 开启地表透明
// window._viewer=viewer
getRightClick()
});
// 每帧都要更新标签位置
function getBubble() {
viewer.scene.postRender.addEventListener(() => {
// console.log("气泡",infos.pups)
infos.pups.forEach((item: any) => {
let worldcoodinate = Cesium.Cartesian3.fromRadians(item.position.longitude, item.position.latitude, item.position.height)
// let screenpops=Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,worldcoodinate)
let screenpops = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, worldcoodinate)
let pupdiv: any = document.getElementById(item.id)
if (pupdiv && screenpops) {
// let infoBox1= new Cesium.InfoBox(document.getElementById(item.id))
pupdiv.style.top = screenpops.y - 80 + 'px'
pupdiv.style.left = screenpops.x + 'px'
let pupdivA: any = document.getElementById(item.id + 'A')
console.log("pupdivA.height:", pupdivA.style.height)
// pupdivA.style.top = screenpops.y-80+25 + 'px'
// pupdivA.style.left = screenpops.x-20+ 'px'
// pupdiv.style.sheet.addRule('#'+'::after', 'content: "";position:absolute; width: 0;height: 0; top: 25px;left: -35px;border-top: 10px solid transparent;border-bottom: 10px solid transparent;border-right: 35px solid #42b983; transform: skewY(-50deg)');
}
})
})
}
// 右击事件
function getRightClick() {
handler.setInputAction(function (event) {
// 此处点击模型
// const pickedObject = viewer.scene.pick(event.position);
let windowpos = viewer.camera.getPickRay(event.position)
// 判断是否点击地球
if (windowpos) {
// pickEllipsoid在加载地形的情况下有一定误差,地形凹凸程度越大,误差越大。
// pickPosition在depthTestAgainstTerrain = false时只能在3DTile上获取准确位置,当depthTestAgainstTerrain = true时,
// 在3DTile和底图上均能获取准确位置
// let cartesian2 = viewer.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid);
var cartesian2 = viewer.scene.pickPosition(event.position)
// console.log("cartesian",cartesian)
let carto2 = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian2)
// if (Cesium.defined(pickedObject)) {
// console.log("右击事件");
// const id = pickedObject.getProperty("id");
// const name = pickedObject.getProperty("name");
// let params = { id: buildUUID(), position: carto2, modelId: id, name }
// ceastPup(params)
// // const entity = pickedObject.id;
// // if (Cesium.defined(entity)) {
// // console.log("右击事件", entity);
// // }
// }
// const id = pickedObject.getProperty("id");
// const name = pickedObject.getProperty("name");
var randomNumber = Math.floor(Math.random() * 10+1);
let params = { id: buildUUID(), position: carto2, modelId: buildUUID(), name: getRandomChineseWord(randomNumber) }
ceastPup(params)
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
}
function getRandomChineseWord(num) {
let arr: any = []
for (var i = 0; i < num; i++) {
var _rsl = "";
// 40869 - 19968 40870 - 19968
var _randomUniCode = Math.floor(Math.random() * (40870 - 19968) + 19968).toString(16);
eval("_rsl=" + '"\\u' + _randomUniCode + '"');
arr.push(_rsl)
}
let chinese = arr.join("")
return chinese;
}
// 创建气泡
function ceastPup(param: any) {
let object: any = infos.pups.find(item => { return item.id == param.id })
if (!object) {
object = new Object()
object.id = param.id
object.position = param.position
infos.pups.push(object)
let divmark = `<div id='${param.id}' style="position:absolute;width:340px;background-color:#42b983;border-radius:5px;color:#fff;
" >
<div id='${param.id}A' style=" position: absolute;
width: 10px;
height: 40px;
top: 35px;
left: -20px;
border-top: 0px solid transparent;
border-bottom: 50px solid transparent;
border-right: 12px solid #42b983;
border-left: 10px solid transparent;
transform: skewY(-50deg);"></div>
<div style="margin-left:20px;margin-top:10px;margin-bottom:10px;margin-right:10px">
<span>Id:${param.modelId}</span>
<span>${param.name}</span></div>
</div>`
// let divmark = "<div id='"+ param.id +"' style='position:absolute;width:200px;height:50px;background-color:#42b983;border-radius:5px;' ></div>"
// console.log("divmark",divmark)
// var style = document.createElement("style");
// document.head.appendChild(style);
// let sheet: any = style.sheet;
// console.log("sheet",sheet)
// // //兼容IE浏览器
// sheet.addRule('#'+param.id+'::after', 'content: "";position:absolute; width: 0;height: 0; top: 25px;left: -35px;border-top: 10px solid transparent;border-bottom: 10px solid transparent;border-right: 35px solid #42b983; transform: skewY(-50deg)');
// $('<style>#'+param.id+'::after{content: "";position:absolute; width: 0;height: 0; top: 25px;left: -35px;border-top: 10px solid transparent;border-bottom: 10px solid transparent;border-right: 35px solid #42b983; transform: skewY(-50deg);}</style>').appendTo('head');
$('#' + viewer._container.id).append(divmark)
getBubble()
}
}
// 随机数字
const buildUUID = () => {
const hexList: string[] = [];
for (let i = 0; i <= 15; i++) {
hexList[i] = i.toString(16);
}
let uuid = "";
for (let i = 1; i <= 36; i++) {
if (i === 9 || i === 14 || i === 19 || i === 24) {
uuid += "-";
} else if (i === 15) {
uuid += 4;
} else if (i === 20) {
uuid += hexList[(Math.random() * 4) | 8];
} else {
uuid += hexList[(Math.random() * 16) | 0];
}
}
return uuid.replace(/-/g, "");
};
// 加载模型
const getasdM = () => {
try {
tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: '../../public/asd/tileset.json',
// type: "3dtiles",
maximumScreenSpaceError: 2, //最大的屏幕空间误差
show: true,
modelMatrix: Cesium.Matrix4.fromArray([0.9920306777526413, 0.035672572522648105, 0.12084122627336652, 0, -0.0052179803729043295, 0.9698924230752208, -0.24347784363696146, 0, -0.12588847079245385, 0.24090694309399502, 0.9623491765937375, 0, -1232.2319169966504, 2358.065217874944, 6764.694671697915, 1]),
}))
viewer.flyTo(tileset)
// viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin); // 开启3D Tiles检测器
} catch (error) {
console.log(`Error loading tileset: ${error}`);
}
}
</script>
<style lang="scss" scoped>
/*--------------------------消息框Start---------------------------*/
.messBox {
display: none;
color: rgb(255, 255, 255);
}
.popup {
position: absolute;
z-index: 100;
}
.closeButton {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
font: 25px/25px Tahoma, Verdana, sans-serif;
color: rgb(255, 255, 255);
text-decoration: none;
font-weight: bold;
background: transparent;
}
.contentWrapper {
max-height: 500px;
overflow-y: auto;
min-height: 180px;
width: 300px;
padding: 1px;
text-align: left;
border-radius: 5px;
background-color: #729ea5;
}
.content {
margin: 5px 20px;
line-height: 1.4;
}
.content div {
text-align: center;
font-size: 18px;
}
.content table {
margin-top: 15px;
}
.content table tr {
height: 25px;
}
/*--------------------------消息框END---------------------------*/
</style>
<style scoped>
.mesaggebox {
/* position: absolute;
left: 50%;
top: 50%; */
}
/* .row-4{
margin: 40px auto;
width: 200px;
height: 50px;
color: #fff;
line-height: 50px;
text-align: center;
position: relative;
background: teal;
border-radius: 5px;
}
.row-4::after{
content: '';
position: absolute;
width: 0;
height: 0;
top: 25px;
right: -20px;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 20px solid teal;
transform: skewY(50deg);
} */
.btnbox {
position: absolute;
top: 10px;
left: 10px;
width: 400px;
.btnboxel {
display: flex;
flex-wrap: wrap;
}
.btnel {
margin-top: 10px;
margin-bottom: 10px;
width: 110px;
/* background: blue; */
}
}
.qnamebox {
position: absolute;
border: 1px solid #ccc;
background: #4cb872;
border-radius: 5px;
padding: 10px;
color: #fff;
}
</style>