实现的效果如下
第一步来定义我们的地图样式
<div class="split-screen-map">
<div class="screen-map-container">
layerValue 表示要分成几个屏
<div v-for="(item, index) in layerValue" :key="index" :id="'screenCesiumContainer' + index" @mouseenter="handleMouseEnter(item, index)"
class="scereen-map-content">
经纬度表示我们划过屏幕可以显示我们当前屏幕的经纬度信息
<!-- 经纬度 -->
<div class="infoText">
<span>{{ item.longitude }}, </span>
<span>{{ item.latitude }}</span>
</div>
</div>
</div>
</div>
<style>
.split-screen-map {
width: 100vw;
height: 100vh;
position: fixed;
z-index: 1999;
padding: 10px;
top: 0;
left: 0;
background: rgba(255, 255, 255, 0.8);
}
.screen-map-container {
height: calc(100vh - 60px);
width: 100%;
display: grid;
grid-template-columns: 50% 50%;
justify-content: center;
}
.scereen-map-content {
border: 1px solid #8d99ff;
height: 100%;
overflow: hidden;
display: grid;
grid-template-rows: repeat(2, 100%);
grid-template-columns: repeat(2, 100%);
position: relative;
}
.infoText {
padding-left: 10px;
text-align: left;
line-height: 26px;
position: absolute;
width: 100%;
height: 26px;
color: #f00;
bottom: 60px;
z-index: 1000;
}
</style>
第二步来初始化地图实现地图的展示、记录鼠标移入地图
let radioValue=4;表示我们要将生成几张地图
function initMap() {
for (let i = 0; i < radioValue; i++) {
let viewerScreen = new Cesium.Viewer('screenCesiumContainer' + i, {
animation: false, //动画
homeButton: false, //home键
geocoder: false, //地址编码
baseLayerPicker: false, //图层选择控件
timeline: false, //时间轴
fullscreenButton: false, //全屏显示
infoBox: false, //点击要素之后浮窗
sceneModePicker: false, //投影方式 三维/二维
sceneMode: Cesium.SceneMode.SCENE2D, //初始场景模式 为二维
navigationInstructionsInitiallyVisible: false, //导航指令
navigationHelpButton: false, //帮助信息
selectionIndicator: false, // 选择
orderIndependentTranslucency: false, // orderIndependentTranslucency需要设置为true,才能去掉地球表面的大气效果的黑圈问题
contextOptions: {
webgl: {
alpha: true,
},
},
})
viewerScreen._cesiumWidget._creditContainer.style.display = 'none' // 隐藏cesium ion
viewerScreen.scene.morphTo2D(0)
将地图定位到地图的位置和高度
viewerScreen.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(111.73, 27.8, radioValue == 2 ? 1200000 : 1700000),
})
viewerScreen.scene.skyBox.show = false
viewerScreen.scene.backgroundColor = new Cesium.Color(0.0, 0.0, 0.0, 0.0)
//设置球体背景色
viewerScreen.scene.globe.baseColor = new Cesium.Color(0, 0, 0, 0)
// 先把所有的影像图层的透明度设置为0
// viewerScreen.imageryLayers._layers.forEach((layer) => {
// // layer.alpha = 0.0;
// viewerScreen.imageryLayers.remove(layer)
// })
// 保存云瑶的图层indexs
// layerValue.value[i].YyImgList.push(addYyImgEvery(viewerScreen, layerValue.value[i].YyImg), 0)
用来保存地图的值
layerValue.value[i].viewerScreen = viewerScreen
}
}
第三步实现鼠标划过记录当前的地图的经纬度信息
-
给地图添加 handleMouseEnter 方法 记录当前鼠标进入了哪个地图
- 计算当前鼠标的经纬度信息并更新
给地图添加 handleMouseEnter 方法 记录当前鼠标进入了哪个地图
<div v-for="(item, index) in layerValue" :key="index" :id="'screenCesiumContainer' + index"
class="scereen-map-content" @mouseenter="handleMouseEnter(item, index)">
<div class="layer-select-class">
<!-- <el-select style="min-width: 230px" v-model="item.layerUrlList" @change="handleSelect(item, index)"
collapse-tags-tooltip collapse-tags multiple filterable placeholder="请选择">
<el-option v-for="val in layerOptions" :key="val.value" :label="val.name" :value="val.value">
</el-option>
</el-select> -->
</div>
</div>
这个方法在初始化中存放
moveLonLatFn(viewerScreen, i)
//计算并保存经纬度信息
function moveLonLatFn(viewerScreen, i) {
new Cesium.ScreenSpaceEventHandler(viewerScreen.scene.canvas).setInputAction(function (movement) {
const res = getLatLon(movement)
layerValue.value[i].longitude = res.longitude
layerValue.value[i].latitude = res.latitude
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}
let currentView = null
let currentIndex = undefined
// 鼠标移入
function handleMouseEnter(item, index) {
currentView = item.viewerScreen
currentIndex = index
}
第四步实现随便一个地图拖拽另外3个地图跟随移动
给地图添加事件
viewerScreen.camera.changed.addEventListener(handleMapChange)
viewerScreen.scene.preRender.addEventListener(handleMapChange)
// 监听地图变化 跟随移动的方法
function handleMapChange() {
if (!currentView) return
const destination = Cesium.Cartographic.toCartesian(currentView.camera.positionCartographic)
layerValue.value.forEach((item, index) => {
if (index != currentIndex) {
item.viewerScreen.camera.setView({
destination: new Cesium.Cartesian3(destination.x, destination.y, destination.z),
orientation: {
direction: currentView.scene.camera._direction,
up: currentView.scene.camera.up,
heading: currentView.scene.camera.heading,
pitch: currentView.scene.camera.pitch,
roll: currentView.scene.camera.roll,
},
})
}
})
}
全部代码
<template>
<div class="split-screen-map">
<div class="screen-map-container">
<div v-for="(item, index) in layerValue" :key="index" :id="'screenCesiumContainer' + index"
class="scereen-map-content" @mouseenter="handleMouseEnter(item, index)">
<div class="layer-select-class">
</div>
<!-- 经纬度 -->
<div class="infoText">
<span>{{ item.longitude }}, </span>
<span>{{ item.latitude }}</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import * as Cesium from 'cesium'
let props = defineProps({
isShowSplitScreen: {
type: Boolean,
default: false,
},
radioValue: {
type: Number,
default: 2,
},
})
let emit = defineEmits(['update:isShowSplitScreen', 'isShowSplitScreenFn'])
let layerValue = ref([])
watch(
() => props.radioValue,
() => {
layerValue.value = []
let defaultUrl = layerOptions.map((item) => item.value)[0]
for (let i = 0; i < props.radioValue; i++) {
// let indexs = layerMapOptions[0].children[0].children.length - 1
// console.log(indexs, 'indexs')
layerValue.value.push({
layerUrlList: [],
layerList: [],
longitude: 112.59,
latitude: 28.12,
viewerScreen: null,
viewEvent: null,
stairModel: 1123,
omenModel: 11232,
// children: layerMapOptions[0].children, //时间轴二级1m列表
// indexs: indexs, //记录云瑶的最大下标
YyImg: {}, //云瑶地址信息
YyImgList: [], //云瑶加过的服务
})
}
nextTick(() => {
initMap()
})
},
{
deep: true,
immediate: true,
}
)
function initMap() {
for (let i = 0; i < props.radioValue; i++) {
let viewerScreen = new Cesium.Viewer('screenCesiumContainer' + i, {
animation: false, //动画
homeButton: false, //home键
geocoder: false, //地址编码
baseLayerPicker: false, //图层选择控件
timeline: false, //时间轴
fullscreenButton: false, //全屏显示
infoBox: false, //点击要素之后浮窗
sceneModePicker: false, //投影方式 三维/二维
sceneMode: Cesium.SceneMode.SCENE2D, //初始场景模式 为二维
navigationInstructionsInitiallyVisible: false, //导航指令
navigationHelpButton: false, //帮助信息
selectionIndicator: false, // 选择
orderIndependentTranslucency: false, // orderIndependentTranslucency需要设置为true,才能去掉地球表面的大气效果的黑圈问题
contextOptions: {
webgl: {
alpha: true,
},
},
})
viewerScreen._cesiumWidget._creditContainer.style.display = 'none' // 隐藏cesium ion
viewerScreen.scene.morphTo2D(0)
viewerScreen.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(111.73, 27.8, props.radioValue == 2 ? 1200000 : 1700000),
})
viewerScreen.scene.skyBox.show = false
viewerScreen.scene.backgroundColor = new Cesium.Color(0.0, 0.0, 0.0, 0.0)
//设置球体背景色
viewerScreen.scene.globe.baseColor = new Cesium.Color(0, 0, 0, 0)
layerValue.value[i].viewerScreen = viewerScreen
//camera监听函数
viewerScreen.camera.changed.addEventListener(handleMapChange)
viewerScreen.scene.preRender.addEventListener(handleMapChange)
//设置触发监听函数的时间
viewerScreen.camera.percentageChanged = 0.01
moveLonLatFn(viewerScreen, i)
}
}
let currentView = null
let currentIndex = undefined
// 鼠标移入
function handleMouseEnter(item, index) {
currentView = item.viewerScreen
currentIndex = index
}
// 监听地图变化
function handleMapChange() {
if (!currentView) return
const destination = Cesium.Cartographic.toCartesian(currentView.camera.positionCartographic)
layerValue.value.forEach((item, index) => {
if (index != currentIndex) {
item.viewerScreen.camera.setView({
destination: new Cesium.Cartesian3(destination.x, destination.y, destination.z),
orientation: {
direction: currentView.scene.camera._direction,
up: currentView.scene.camera.up,
heading: currentView.scene.camera.heading,
pitch: currentView.scene.camera.pitch,
roll: currentView.scene.camera.roll,
},
})
}
})
}
}
//滑动获取点经纬度
function moveLonLatFn(viewerScreen, i) {
new Cesium.ScreenSpaceEventHandler(viewerScreen.scene.canvas).setInputAction(function (movement) {
const res = getLatLon(movement)
layerValue.value[i].longitude = res.longitude
layerValue.value[i].latitude = res.latitude
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}
// 组件卸载之前销毁地图
onUnmounted(() => {
if (layerValue.value && layerValue.value.length) {
layerValue.value.forEach((item) => {
if (item.viewerScreen) {
item.viewerScreen.destroy()
item.viewerScreen = null
}
})
}
})
</script>
<style scoped lang="scss">
.split-screen-map {
width: 100vw;
height: 100vh;
position: fixed;
z-index: 1999;
padding: 10px;
top: 0;
left: 0;
background: rgba(255, 255, 255, 0.8);
}
.switch_time_line {
position: absolute;
right: 85px;
top: 9px;
display: flex;
align-items: center;
font-size: 12px;
}
.close-btn {
width: 100%;
text-align: right;
cursor: pointer;
}
.screen-map-container {
height: calc(100vh - 60px);
width: 100%;
display: grid;
grid-template-columns: 50% 50%;
justify-content: center;
}
.scereen-map-content {
border: 1px solid #8d99ff;
height: 100%;
overflow: hidden;
display: grid;
grid-template-rows: repeat(2, 100%);
grid-template-columns: repeat(2, 100%);
position: relative;
}
.infoText {
padding-left: 10px;
text-align: left;
line-height: 26px;
position: absolute;
width: 100%;
height: 26px;
color: #f00;
bottom: 60px;
z-index: 1000;
}
.scereen-map-content:nth-child(2) {
margin-left: 5px;
}
.scereen-map-content:nth-child(3) {
margin-top: 5px;
}
.scereen-map-content:nth-child(4) {
margin-left: 5px;
margin-top: 5px;
}
.layer-select-class {
position: absolute;
top: 0;
left: 0;
display: flex;
width: 100%;
padding-top: 5px;
justify-content: space-around;
align-items: center;
z-index: 10;
}
.time_line_sceren {
position: absolute;
bottom: 1px;
}
// #timeAxisLeft {
// position: absolute;
// bottom: 0px;
// width: 100%;
// left: 0;
// }
// .timer_shaft {
// // width: 840px;
// /* position: absolute; */
// display: flex;
// align-items: center;
// position: relative;
// bottom: 1px;
// z-index: 999;
// height: 66px;
// background: #eee;
// border-radius: 5px;
// opacity: 0.9;
// .select-type {
// // position: absolute;
// // top: 20px;
// // left: 15px;
// display: flex;
// }
// .time_inner {
// width: calc(100% - 250px);
// // position: absolute;
// position: relative;
// display: flex;
// margin-left: 3%;
// margin-bottom: 20px;
// .time_inner_left {
// position: absolute;
// left: -15px;
// top: -2px;
// font-size: 24px;
// cursor: pointer;
// }
// .time_inner_right {
// position: absolute;
// right: -33px;
// top: -2px;
// font-size: 24px;
// cursor: pointer;
// }
// .time_inner_center {
// height: 20px;
// margin-left: 10px;
// display: flex;
// position: absolute;
// top: 0;
// left: 0;
// justify-content: space-evenly;
// border-radius: 8px;
// background: linear-gradient(180deg, #2f97fe, #0262c1);
// .long_css {
// width: calc(100% / 4);
// // width: 4px;
// // border-right: 4px;
// // border-color: black;
// // border-width:;
// border-right: 1px solid black;
// background-color: red;
// height: 100%;
// // height: 100%;
// // background-color: black;
// // margin-right: calc(100% / 5);
// // margin-left: calc((100% - 14px) / 5);
// }
// // .long_css:nth ::after {
// // content: '';
// // width: calc(100% / 4);
// // // width: 4px;
// // // border-right: 4px;
// // // border-color: black;
// // // border-width:;
// // border-right: 1px solid black;
// // background-color: red;
// // height: 100%;
// // }
// }
// }
// }
</style>