赞
踩
需求:点击三维地图上的标注展示弹窗,随着地图移动弹窗也需要移动,缩小地图比例要隐藏,反之显示。
效果图如下:
话不多说,直接上代码:
父组件:
- <template>
- <div id="cesiumContainer" />
- <div id="popup">
- <OverlayChart
- v-if="cesiumGather.popVisible"
- :overlay-chart-obj="cesiumGather.overlayChartObj"
- />
- </div>
- </template>
-
- <script setup>
- import * as Cesium from "cesium";
- import { reactive, onMounted } from "vue";
- import OverlayChart from "../../components/overlayChart.vue";
-
- const cesiumGather = reactive({
- popVisible: false,
- overlayChartObj: {},
- cesiumViewer: null,
- });
-
- onMounted(() => {
- cesiumGather.cesiumViewer = mapCreate();
- mapCesiumData();
- });
- // 初始化地图
- const mapCreate = () => {
- // 添加图层
- const viewer = new Cesium.Viewer("cesiumContainer", {
- geocoder: false, //搜索框
- homeButton: false, //home键
- animation: false, //动画控件
- fullscreenButton: false, //全屏按钮
- sceneModePicker: false, //场景模式选择器
- timeline: false, //时间轴
- navigationHelpButton: false, //导航提示
- baseLayerPicker: false, //地图选择器
- infoBox: false, //是否显示信息框
- scene3DOnly: false, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
- selectionIndicator: false, //是否显示选取指示器组件
- baselLayerPicker: false, // 将图层选择的控件关掉,才能添加其他影像数据
- });
- viewer._cesiumWidget._creditContainer.style.display = "none";
- return viewer;
- };
-
- // 获取聚合数据
- const mapCesiumData = () => {
- let queryData = [
- { lng: 104.023442, lat: 23.44321, name: "标点一" },
- { lng: 134.023442, lat: 27.44321, name: "标点二" },
- { lng: 105.023442, lat: 32.44321, name: "标点三" },
- { lng: 104.023442, lat: 23.44221, name: "标点四" },
- { lng: 105.023442, lat: 13.44321, name: "标点五" },
- { lng: 114.023442, lat: 33.44321, name: "标点六" },
- { lng: 124.023442, lat: 43.42321, name: "标点七" },
- { lng: 134.023442, lat: 33.42321, name: "标点八" },
- { lng: 144.023442, lat: 53.14321, name: "标点九" },
- { lng: 101.023442, lat: 23.44321, name: "标点十" },
- ];
- // 加载点位
- renderCesiumPoint(cesiumGather.cesiumViewer, queryData);
-
- // 添加点击事件
- handlePinClick();
- };
-
- // 加载点位
- const renderCesiumPoint = (cesiumViewer, projectList) => {
- cesiumViewer.entities.removeAll();
- for (let i = 0; i < projectList.length; i++) {
- const pro = projectList[i];
- cesiumViewer.entities.add({
- position: Cesium.Cartesian3.fromDegrees(pro.lng, pro.lat, 1000),
- name: pro.name,
- property: pro, //自己加的相关属性,弹窗里需要用到
- billboard: {
- //图标
- image: "./static/images/markers/4.png",
- scale: 1, //图标比例
- width: 36,
- height: 36,
- // 垂直方向
- verticalOrigin: Cesium.VerticalOrigin.BASELINE,
- //水平方向
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
- },
- label: {
- // 文字标签
- text: pro.name,
- scale: 1,
- font: "16px monospace",
- fillColor: Cesium.Color.WHITE,
- showBackground: true, //设置背景颜色
- pixelOffset: new Cesium.Cartesian2(0, -44), //设置左右、上下移动
- // 垂直方向
- verticalOrigin: Cesium.VerticalOrigin.BASELINE,
- //水平方向
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
- },
- });
- }
- };
-
- // 点击地图上的点
- const handlePinClick = () => {
- const cesiumViewer = cesiumGather.cesiumViewer;
- const handle3D = new Cesium.ScreenSpaceEventHandler(
- cesiumViewer.scene.canvas
- );
- handle3D.setInputAction((movement) => {
- const pick = cesiumViewer.scene.pick(movement.position);
- console.log(pick);
- if (!pick) {
- cesiumGather.popVisible = false;
- // 清除监听事件
- cesiumViewer.scene.postRender.removeEventListener(infoWindowPostRender);
- return;
- }
- const obj = pick.id.property;
- const coordinate = movement.position;
- // 解决点击不同点数据不更换问题
- if (cesiumGather.overlayChartObj != {}) {
- cesiumGather.popVisible = false;
- cesiumGather.overlayChartObj = {};
- }
- /*overlayChartObj是传给子组件(弹窗)的数据*/
- cesiumGather.overlayChartObj = obj;
- showOverlayChart(coordinate);
- // 添加地图移动监听:使地图移动弹窗跟着移动
- cesiumViewer.scene.postRender.addEventListener(infoWindowPostRender);
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
- };
-
- //显示图表
- const showOverlayChart = (position) => {
- const pop = document.getElementById("popup");
- pop.style.position = "absolute";
- pop.style.top = position.y - 100 + "px";
- pop.style.left = position.x - 120 + "px";
- pop.style.zIndex = 99;
- cesiumGather.popVisible = true;
- };
- // 地图移动时弹窗跟随
- const infoWindowPostRender = () => {
- const cesiumViewer = cesiumGather.cesiumViewer;
- //经纬度转为世界坐标
- const gisPosition = Cesium.Cartesian3.fromDegrees(
- Number(cesiumGather.overlayChartObj.lng),
- Number(cesiumGather.overlayChartObj.lat),
- 2500
- );
- //转化为屏幕坐标
- var windowPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
- cesiumViewer.scene,
- gisPosition
- );
- //解决滚动不隐藏问题
- const camerPosition = cesiumViewer.camera.position;
- let height =
- cesiumViewer.scene.globe.ellipsoid.cartesianToCartographic(
- camerPosition
- ).height;
- height += cesiumViewer.scene.globe.ellipsoid.maximumRadius;
-
- if (
- !(Cesium.Cartesian3.distance(camerPosition, gisPosition) > height) &&
- cesiumViewer.camera.positionCartographic.height < 50000000
- ) {
- cesiumGather.popVisible = true;
- } else {
- cesiumGather.popVisible = false;
- }
- if (Cesium.defined(windowPosition)) {
- setPopPosition(windowPosition);
- }
- };
- const setPopPosition = (position) => {
- const pop = document.getElementById("popup");
- pop.style.top = position.y - 100 + "px";
- pop.style.left = position.x - 120 + "px";
- };
- </script>
-
- <style scoped></style>
子组件:
- <template>
- <div class="cesium-popup">
- <span>姓名:{{ overlayChartObj.name }}</span><br/>
- <span>坐标:X:{{ overlayChartObj.lat }},Y:{{ overlayChartObj.lng }}</span>
- </div>
- </template>
- <script setup>
- // props父传子
- const props = defineProps({
- overlayChartObj: {
- type: Object,
- default: function () {
- return {};
- },
- },
- });
- </script>
- <style lang="scss" scoped>
- .cesium-popup{
- width: 240px;
- height: 50px;
- background-color: #3df;
- span{
- font-size: 14px;
- }
- }
- </style>
这里的弹窗样式笔者随便弄了一下,你们可以自行发挥,有哪块不懂的随时联系笔者。
借鉴文章:cesium自定义弹窗
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。