cesium自定图弹框根据经纬度弹框
token记得换成您自己的!!!
申请cesium的token 官网【Cesium: The Platform for 3D Geospatial】
pickEllipsoid在加载地形的情况下有一定误差,地形凹凸程度越大,误差越大。
pickPosition在depthTestAgainstTerrain = false时只能在3DTile上获取准确位置,当depthTestAgainstTerrain = true时, 在3DTile和底图上均能获取准确位置
viewer.scene.globe.depthTestAgainstTerrain = true; // 开启地形深度检测
javascript
<template>
<div id="cesiumContainer"></div>
<div class="btnbox">
<div class="btnboxel">
<el-button class="btnel" v-for="item in pointData2" :key="item.modelId" @click="showBubble(item)">
<span>{{ item.name }}</span>
</el-button>
<el-button class="btnel" @click="testClick">测试</el-button>
</div>
</div>
<div id="infoboxs" :style="qnameclass" class="qnamebox" :class="qname.type == '1' ? 'qnameback' : ''">
<div class="spanbox">
<span>编号:{{ qname.id }}</span>
<span>名称:{{ qname.name }}</span>
<span>创建时间:2024-07-01</span>
<img src="//img.isqqw.com/profile/upload/2023/11/15/fabee49f-3e3b-45a6-a5d5-2780f5684bde.png" alt="">
</div>
</div>
<div class="bulletframe_box" v-if="isShowBullet" :style="pierpop">
<el-icon class="closeicon" @click="closebtn" color="#fff" size="28"
><Close
/></el-icon>
<span class="bulletframe_title">{{titleVal.data.name}}</span>
<div class="bulletframe_textbox">
<p>类型:{{Number(titleVal.data.type)==1?'蓝色':'黄色'}}</p>
<p>状态:{{titleVal.data.state}}</p>
<p>设备编号:{{titleVal.data.modelId}}</p>
</div>
</div>
<el-button class="btndown">地图等级:{{ zoomlevel }}</el-button>
<el-button type="success" class="btndown sucess" @click="clickDJ">等级切换</el-button>
</template>
<script setup lang='ts'>
import { Close } from "@element-plus/icons-vue";
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";
// import u305 from "../assets/u305.png";
import u233 from "../assets/u233.png";
import u236 from "../assets/u236.png";
// 地图实例
let viewer: any;
let tileset; //设置一个变量来存放通过3DTiles创建的模型
let handler
let selectedFeature
const selected = {
feature: undefined,
originalColor: new Cesium.Color(),
};
let qname = reactive({
id: '',
name: '',
type: ''
})
let qnameclass = reactive({
top: '',
left: '',
})
let valshow
// 地图等级
let zoomlevel = ref()
let infos: any = reactive({
pups: []
})
let infoBox1 = ref()
// 桥梁信息 假数据
let pointData2 = [
{
type: 1,
lat: 117.3429,
lon: 24.6820,
name: "心若向阳",
text: "心若向阳",
modelId: 'ASDFGH_6'
},
{
type: 1,
lat: 117.2735,
lon: 24.0485,
name: "无畏悲伤",
text: "无畏悲伤",
modelId: 'ASDFGH_7'
},
{
type: 1,
lat: 117.25106,
lon: 24.09902,
name: "常青桥",
text: "常青桥",
modelId: 'ASDFGH_8'
},
{
type: 1,
lat: 117.3987,
lon: 24.8927,
name: "常青藤下",
text: "常青藤下",
modelId: 'ASDFGH_9'
},
{
type: 2,
lat: 117.1593,
lon: 23.819,
name: "常青果",
text: "常青果",
modelId: 'ASDFGH_16'
},
{
type: 2,
lat: 117.9352,
lon: 24.9933,
name: "常青树上",
text: "常青树上",
modelId: 'ASDFGH_17'
},
{
type: 2,
lat: 117.8939,
lon: 24.8584,
name: "山河已秋",
text: "山河已秋",
modelId: 'ASDFGH_18'
},
{
type: 2,
lat: 117.3113,
lon: 24.613,
name: "人间已晚",
text: "人间已晚",
modelId: 'ASDFGH_19'
},
];
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版权
// handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 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; // 开启地表透明
labelData()
viewer.camera.moveEnd.addEventListener(onMoveendMap);
getFirst()
getmap()
mapLoading()
});
function showBubble(item) {
qname.name = item.name
qname.id = item.modelId
qname.type = item.type
console.log("item",item)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(item.lat, item.lon, 1000),
duration: 2, // 飞行动画持续时间(单位:秒)
});
viewer.scene.postRender.addEventListener(() => {
let worldPosition = Cesium.Cartesian3.fromDegrees(item.lat, item.lon)
let screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, worldPosition)
if (screenPosition) {
qnameclass.top = screenPosition.y + 'px'
qnameclass.left = screenPosition.x + 'px'
}
})
}
function testClick(){
qname.name = "测试"
qname.id = "AAAccc1234569"
qname.type ="1"
let pointData :any ={x:-2176578.86625116,y:4386183.52410871,z:4073474.05620639}
// let pointData :any ={x:-2177374.161524288,y:4388442.775493362,z:4070640.6013179137}
let gspdata=cartesian3ToGps(viewer,pointData)
console.log("gspdata",gspdata)
let lat=gspdata[0]
let lon=gspdata[1]
let het=gspdata[2]
viewer.camera.flyTo({
// destination: Cesium.Cartesian3.fromDegrees(lat, lon, 1000),
destination: Cesium.Cartesian3.fromDegrees(lat, lon, het),
duration: 2, // 飞行动画持续时间(单位:秒)
});
viewer.scene.postRender.addEventListener(() => {
let worldPosition = Cesium.Cartesian3.fromDegrees(lat, lon)
let screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, worldPosition)
console.log("screenPosition:",screenPosition)
if (screenPosition) {
qnameclass.top = screenPosition.y + 'px'
qnameclass.left = screenPosition.x + 'px'
}
})
}
/**
* cartesian3转gps
* @param viewer
* @param cartesian
* @returns
*/
const cartesian3ToGps = (
viewer: Cesium.Viewer,
cartesian: Cesium.Cartesian3
): number[] => {
const cartographic =
viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
return [
Cesium.Math.toDegrees(cartographic.longitude),
Cesium.Math.toDegrees(cartographic.latitude),
cartographic.height,
];
};
function labelData() {
const translucencyByDistance2 = new Cesium.NearFarScalar(
20000,
1,
150000,
0.7
);
pointData2.forEach((k) => {
const label = viewer.entities.add({
name: k.name,
position: Cesium.Cartesian3.fromDegrees(
k.lat,
k.lon,
50
),
label: {
text: k.name,
// 字体大小
font: "18px sans-serif",
// FILL填充/OUTLINE描边/FILL_AND_OUTLINED填充描边
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// 描边颜色
outlineColor: Cesium.Color.WHITE,
// 描边宽度
outlineWidth: 5,
// 字体颜色
fillColor: Cesium.Color.BLUE,
pixelOffset: new Cesium.Cartesian2(0, -30), // 视角偏移
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0,
150000
), // 可视范围
// translucencyByDistance: translucencyByDistance2,
},
});
})
}
function clickDJ(){
// viewer.camera.zoomIn(5); // amount是一个可选的浮点数值,表示放大的数量
viewer.camera.zoomOut(5876); // amount是一个可选的浮点数值,表示缩小的数量
// viewer.camera.changed.addEventListener(SetLevel)
// setViewerRange(viewer,100,500)
}
//设置地图最大最小显示范围
function setViewerRange(viewer, minZoom, maxZoom){
minZoom = (minZoom==undefined) ? 50 : minZoom;
maxZoom = (maxZoom==undefined) ? 550 : maxZoom;
viewer.scene.screenSpaceCameraController.minimumZoomDistance = minZoom;
viewer.scene.screenSpaceCameraController.maximumZoomDistance = maxZoom;
}
function SetLevel(){
var tileRender=viewer.scene.globe._surface._tilesToRender;
if(tileRender&&tileRender.length>0){
console.log("当前级别:"+tileRender[0]._level+"级");
}
}
function onMoveendMap() {
// 获取当前相机高度
let height = Math.ceil(viewer.camera.positionCartographic.height);
console.log("高度:",height)
let zoom = heightToZoom(height);
zoomlevel.value = zoom;
}
function getFirst() {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(117.3987, 24.8927, 700),
duration: 2, // 飞行动画持续时间(单位:秒)
});
qname.name = '桥内特大桥'
qname.id = 'ASDFGH_9'
qname.type = '1'
viewer.scene.postRender.addEventListener(() => {
let worldPosition = Cesium.Cartesian3.fromDegrees(117.3987, 24.8927)
let screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, worldPosition)
if (screenPosition) {
qnameclass.top = screenPosition.y + 'px'
qnameclass.left = screenPosition.x + 'px'
}
})
}
function heightToZoom(height) {
var A = 40487.57;
var B = 0.00007096758;
var C = 91610.74;
var D = -40467.74;
return Math.round(D + (A - D) / (1 + Math.pow(height / C, B)));
}
let mapacarDataList: any = ref([]);
/**
* 弹框是否显示
*/
let isShowBullet = ref(false);
/**
* 弹框样式
*/
let pierpop = ref({
top: "",
left: "",
});
let titleVal=reactive({
data:{
name:'',
type:"",
state:'',
modelId:'',
}
})
/**
* 地图数据列表
*/
const getmap = () => {
mapacarDataList.value.push(
{
id: 1,
name: "心若向阳",
type: 2,
state: "完成",
modelId: 'ASDFGH_6',
lat: 117.3429,
lng: 24.6820,
},
{
id: 2,
type: 1,
state: "排到",
name: "无畏悲伤",
lat: 117.2735,
lng: 24.0485,
modelId: 'ASDFGH_7'
},
{
id: 3,
type: 2,
state: "运输",
name: "常青桥",
lat: 117.25106,
lng: 24.09902,
modelId: 'ASDFGH_8'
},
{
id: 4,
type: 1,
state: "装货",
name: "常青藤下",
lat: 117.3987,
lng: 24.8927,
modelId: 'ASDFGH_9'
},
{
id: 5,
type: 1,
state: "装货",
name: "常青果",
lat: 117.1593,
lng: 23.819,
modelId: 'ASDFGH_16'
},
{
id: 6,
name: "常青树上",
type: 2,
state: "完成",
modelId: 'ASDFGH_17',
lat: 117.9352,
lng: 24.9933,
},
{
id: 7,
type: 1,
state: "排到",
name: "山河已秋",
lat: 117.8939,
lng: 24.8584,
modelId: 'ASDFGH_18'
},
{
id: 8,
type: 2,
state: "运输",
name: "人间已晚",
lat: 117.3113,
lng: 24.613,
modelId: 'ASDFGH_19'
},
);
};
/**
* 关闭按钮
*/
const closebtn = () => {
isShowBullet.value = false;
};
/**
* 地图加载点位
*/
const mapLoading = () => {
// 定义初始位置
let position = Cesium.Cartesian3.fromDegrees(117.48295010826752,24.866476112918775, 150000);
viewer.camera.flyTo({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0.0,
},
duration: 2,
complete: function () {
getDataList();
},
});
// 监听鼠标点击事件
viewer.screenSpaceEventHandler.setInputAction((event: any) => {
const position = viewer.scene.pickPosition(event.position);
if (Cesium.defined(position)) {
const cartographic = Cesium.Cartographic.fromCartesian(position);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
console.log(`Longitude: ${longitude}, Latitude: ${latitude}`);
// 这里可以处理获取到的经纬度数据
}
const pickedFeature = viewer.scene.pick(event.position);
if (pickedFeature) {
if (pickedFeature.id && pickedFeature.id._id) {
const result = mapacarDataList.value.filter(
(item: any) => item.id == pickedFeature.id._id
);
// console.log("经度", result);
// console.log("经度", result[0].lat);
// console.log("纬度", result[0].lng);
titleVal.data=result[0]
let worldPosition = Cesium.Cartesian3.fromDegrees(
result[0].lat,
result[0].lng
);
let screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
worldPosition
);
if (screenPosition) {
isShowBullet.value = true;
pierpop.value.top = `${screenPosition.y - 310}px`;
pierpop.value.left = `${screenPosition.x - 168}px`;
}
// 监听场景渲染事件
viewer.scene.postRender.addEventListener(() => {
let worldPositionNew = Cesium.Cartesian3.fromDegrees(
result[0].lat,
result[0].lng
);
let screenPositionNew =
Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
worldPositionNew
);
if (screenPositionNew) {
pierpop.value.top = `${screenPositionNew.y - 310}px`;
pierpop.value.left = `${screenPositionNew.x - 168}px`;
}
});
console.log("screenPositionNew", screenPosition);
} else {
return;
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
/**
* 渲染贴图
*/
const getDataList = () => {
mapacarDataList.value.map((item: any) => {
let carimg = "";
if (item.type == 1) {
carimg = u233;
} else {
carimg = u236;
}
getImgLabeMap(carimg, item.lat, item.lng, item.id, item.name);
});
};
const getImgLabeMap = (
img?: string,
lat?: number,
lng?: number,
id?: string | number,
name?: string
) => {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(lat!, lng!, 1),
billboard: {
image: img,
scale: 1,
// pixelOffset: new Cesium.Cartesian2(-45, -35),
},
id: id,
name: name,
});
// viewer.zoomTo(viewer.entities);
};
let entityIDgetList: string[] = [];
/**
* 监听鼠标已入事件
*/
viewer.screenSpaceEventHandler.setInputAction(
function onMouseMove(movement: any) {
const pickedObject = viewer.scene.pick(
movement.endPosition
);
if (pickedObject && pickedObject.id) {
// 添加小手
(viewer.container as HTMLDivElement).style.cursor =
"pointer";
} else {
// 还原
(viewer.container as HTMLDivElement).style.cursor =
"default";
}
},
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
};
</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%; */
}
.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; */
margin-left: 0;
margin-right: 12px;
}
}
.qnamebox {
position: absolute;
border: 1px solid #ccc;
/* background: #4cb872; */
width: 180px;
background: linear-gradient(90deg, rgba(15, 100, 0, 0.62) 71%, rgba(15, 100, 0, 0.55) 45%);
background-size: 100% 100%;
border-radius: 5px;
padding: 10px;
color: #fff;
.spanbox {
display: flex;
flex-wrap: wrap;
border: 1px solid #fff;
border-radius: 3px;
span {
border-bottom: 1px solid #fff;
display: inline-block;
width: 100%;
height: 40px;
line-height: 40px;
padding-left: 10px;
/* border-left:1px solid #fff;
border-right: 1px solid #fff; */
}
span:last-child {
border-bottom: none;
}
}
}
.qnameback {
background: linear-gradient(90deg, rgba(0, 62, 100, 0.62) 71%, rgba(1, 63, 97, 0.55) 45%);
}
.btndown {
position: absolute;
left: 0;
bottom: 0;
}
.sucess{
left:110px;
}
.bulletframe_box {
position: absolute;
width: 331px;
height: 254px;
background: url("../assets/u305.png") no-repeat;
display: flex;
position: absolute;
.closeicon {
position: absolute;
right: 5px;
top: 5px;
cursor: pointer;
}
.bulletframe_title{
position: relative;
color: #fff;
top: 53%;
left: 50%;
transform: translate(-50%,-50%);
}
.bulletframe_textbox {
width: 80%;
height: 80%;
/* // background: red; */
margin: auto;
display: flex;
flex-direction: column;
justify-content: center;
p {
margin: 0;
padding: 0;
line-height: 30px;
color: #fff;
margin-left: 25px;
}
}
}
</style>