一、前言
上一篇文章:【Cesium】五、地图实现鹰眼效果(三维),虽然实现了3D 的鸟瞰图效果,但是只有鸟瞰图跟着 主地图在动,如果 在鸟瞰图上操作 主地图却不会跟着同步。本文则是实现主地图与鸟瞰图的联动效果。
本文参考文章:cesium实现鹰眼地图(三维)与主图联动效果
二、效果
三、实现方法
2.1 思路
鹰眼地图与主图联动,需要判断是主图在动,还是鹰眼地图在动,即需要判断触发事件,否者会造成循环联动,无法实现效果。
2.2 方法
utils
下新建HawkEye3DMap.js
文件,代码如下:
import * as Cesium from "cesium";
/**
* @description: 三维鹰眼地图及与主图联动
* @param {*}
* @return {*}
*/
export class HawkEye3DMap {
constructor(viewer) {
// 主图
this._viewer = viewer;
// 鹰眼图
this._hawkEyeMap = null;
// 判断事件是主图触发还是鹰眼地图触发
this._isMainMapTrigger = false;
this._isEyeMapTrigger = false;
}
// 初始化函数
_init() {
this._divInit();
this._mapInit();
}
// 创建div,并设置样式
_divInit() {
let hawkEyeDiv = document.createElement("div");
hawkEyeDiv.setAttribute('id', "hawkEye3dMap");
hawkEyeDiv.style.cssText = "position: absolute;left: 70% ;top: 2% ;border-radius: 50% ;height: 160px;width: 160px;overflow: hidden;border: 2px solid #002FA7;"
document.getElementsByTagName("body").item(0).appendChild(hawkEyeDiv);
};
_mapInit() {
// div创建完成后才能初始化地图,否则会找不到div保错
// 初始化地图
this._hawkEyeMap = new Cesium.Viewer('hawkEye3dMap', {
infoBox: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
baseLayerPicker: false,
navigationHelpButton: false,
animation: false,
timeline: false,
fullscreenButton: false,
});
this._hawkEyeMap.cesiumWidget.creditContainer.style.display = 'none';
this._hawkEyeMap.scene.backgroundColor = Cesium.Color.TRANSPARENT;
this._hawkEyeMap.imageryLayers.removeAll();
// 鹰眼图中添加高德路网中文注记图(鹰眼图中坐标偏移一点不影响)
this._hawkEyeMap.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
minimumLevel: 3,
maximumLevel: 18
})
);
// 引起事件监听的相机变化幅度
this._viewer.camera.percentageChanged = 0.02;
this._hawkEyeMap.camera.percentageChanged = 0.5;
this._bindEvent();
}
// 绑定事件
_bindEvent() {
// 鹰眼与主图同步
this._viewer.camera.changed.addEventListener(this._syncEyeMap, this);
// 第一次刷新渲染时联动
this._viewer.scene.preRender.addEventListener(this._syncEyeMap, this);
// 主图与鹰眼图同步
this._hawkEyeMap.camera.changed.addEventListener(this._syncMap, this);
this._hawkEyeMap.scene.preRender.addEventListener(this._syncMap, this);
}
// 同步主图与鹰眼地图
_syncEyeMap() {
// 监听主图
new Cesium.ScreenSpaceEventHandler(this._viewer.canvas).setInputAction(() => {
this._isMainMapTrigger = true;
this._isEyeMapTrigger = false;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 判断是否为主图移动
if (!this._isMainMapTrigger) {
return false;
}
this._hawkEyeMap.camera.flyTo({
destination: this._viewer.camera.position,
orientation: {
heading: this._viewer.camera.heading,
pitch: this._viewer.camera.pitch,
roll: this._viewer.camera.roll,
},
duration: 0.0,
})
}
// 鹰眼地图与主图联动效果
_syncMap() {
// 监听鹰眼地图
new Cesium.ScreenSpaceEventHandler(this._hawkEyeMap.canvas).setInputAction(() => {
this._isMainMapTrigger = false;
this._isEyeMapTrigger = true;
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
// 判断是否为鹰眼地图移动
if (!this._isEyeMapTrigger) {
return false;
}
this._viewer.camera.flyTo({
destination: this._hawkEyeMap.camera.position,
orientation: {
heading: this._hawkEyeMap.camera.heading,
pitch: this._hawkEyeMap.camera.pitch,
roll: this._hawkEyeMap.camera.roll,
},
duration: 0.0,
})
}
}
2.3 使用
首先在vue文件中引入刚刚的js文件
import { HawkEye3DMap } from "@/utils/HawkEye3DMap.js"
随后在script 中调用方法
// 鹰眼地图初始化 联动效果
let hawkEyeMap = new HawkEye3DMap(viewer);
hawkEyeMap._init();
App.vue
上面是部分代码,下面附上App.vue的全部代码,仅供参考
<template>
<div id="cesiumContainer"></div>
<div id="hawkEyeMap"></div>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import * as Cesium from "cesium";
import { HawkEye3DMap } from "@/utils/HawkEye3DMap.js"
const initFn = async () => {
const viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
baseLayerPicker: true,
navigationHelpButton: false,
animation: false,
timeline: false,
fullscreenButton: false,
vrButton: false,
});
viewer._cesiumWidget._creditContainer.style.display = "none"; //取消版权信息
const imageLayers = viewer.scene.imageryLayers;
imageLayers.remove(imageLayers.get(0)); //移除默认影像图层
const TDTTK = "337bc7a038fe9d239af76ab013ff4594"; //填入你自己的天地图Key
// 天地图影像
const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdt",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
viewer.imageryLayers.addImageryProvider(tdtLayer);
// 天地图注记
const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdtAnno",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
// 鹰眼地图初始化 联动效果
let hawkEyeMap = new HawkEye3DMap(viewer);
hawkEyeMap._init();
};
onMounted(() => {
// Cesium 初始化
initFn();
});
</script>
<style>
#app {
width: 100%;
height: 100%;
font-family: sans-serif;
text-align: center;
}
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
/* 鹰眼图样式 */
#hawkEyeMap {
position: absolute;
left: 70%;
top: 2%;
border-radius: 50%;
height: 160px;
width: 160px;
overflow: hidden;
border: 2px solid #002FA7;
}
</style>
后面我还会更新更多关于cesium知识,敬请关注。