cesium-添加点并且可以编辑

2023-11-17

完整代码

<template>
  <div class="my_mark">
    <div class="mark_tool">
      <div class="tool_e">
        <div class="tool_b" @click="handleAddPoint">
          <el-tooltip content="添加标记" effect="customized">
            <el-icon size="22">
              <Edit />
            </el-icon>
          </el-tooltip>
        </div>
      </div>
     
     
      <div class="tool_d">
        <div class="tool_b" @click="removeAllPoints">
          <el-tooltip content="清空标记" effect="customized">
            <el-icon size="22">
              <Delete />
            </el-icon>
          </el-tooltip>
        </div>
        <!-- <div
          class="tool_b"
          @click="
            () => {
              isEdit = !isEdit;
            }
          "
        >
        
      </div>
    </div>
    <div style="margin-top: 10px">
      <el-table
        :data="popupInfo"
        border
        :default-sort="{ prop: 'name', order: 'descending' }"
        style="width: 100%"
        class="table"
        @row-click="handleRow"
      >
        <el-table-column prop="name" label="名称" width="180" sortable />
        <el-table-column label="操作" align="center">
          <template #default="scope">
            <el-icon size="16" @click="deletePoint(scope.row)">
              <Delete />
            </el-icon>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>

  <!-- 标记弹框 -->
  <div
    class="popover"
    ref="popup"
    :style="{ left: popupLeft, top: popupTop, display: popupDisplay }"
  >
    <div class="header">
      <div @click="closePopup">
        <el-icon>
          <CloseBold />
        </el-icon>
      </div>
      <div class="font">我的标记</div>
    </div>
    <div class="container">
      <el-row>
        <el-col :span="4">名称:</el-col>
        <el-col :span="20">
          <el-input v-model="pointInfo.name" placeholder="请输入" clearable />
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="4">备注:</el-col>
        <el-col :span="20">
          <el-input
            v-model="pointInfo.remark"
            placeholder="请输入备注"
            style="height: 50px"
            clearable
          />
        </el-col>
      </el-row>
    </div>
    <div class="btn">
      <el-button type="primary" plain @click="handleSave">确定</el-button>
    </div>
  </div>
  <!-- 鼠标移入展示内容 -->
  <div
    class="Mouse"
    ref="tooltip"
    :style="{ left: tooltipLeft, top: tooltipTop, display: tooltipDisplay }"
  >
    拖动该点后修改位置
  </div>
</template>
<script setup lang="ts">
import { ref, inject, watch, onUnmounted } from 'vue';
import {
  Viewer,
  ScreenSpaceEventHandler,
  Cartographic,
  Math,
  ScreenSpaceEventType,
  Cartesian2,
  Entity,
  Cartesian3,
  defined,
  Color,
  ConstantPositionProperty
} from 'cesium';

import SvgIcon from '../icons/SvgIcon.vue';
import { point } from '@turf/helpers';

const viewer: Viewer = inject('viewer')!;
// 是否可编辑
// const isEdit = ref(true);
// 存储绘制的点
const pointsEntity = ref<any>([]);
// 屏幕事件
const handlerPoint = ref();
//标记点的信息
const pointInfo = ref({
  name: '我的标记点',
  remark: ''
});
//弹窗控制
const popup = ref();
const popupDisplay = ref('none');
const popupLeft = ref('0px');
const popupTop = ref('0px');
const popupInfo = ref<
  {
    name: string;
    remark: string;
    id: string;
  }[]
>([]);
const idNum = ref(0);
//提示位置
const tooltip = ref();
const tooltipDisplay = ref('none');
const tooltipLeft = ref('0px');
const tooltipTop = ref('0px');
/**
 * 添加点
 */
const handleAddPoint = () => {
  // 设置鼠标样式为crosshair
  document.body.style.cursor = 'crosshair';
  handlerPoint.value = new ScreenSpaceEventHandler(viewer.canvas);
  handlerPoint.value.setInputAction(function (click: { position: Cartesian2 }) {
    const cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);
    if (cartesian) {
      const cartographic = Cartographic.fromCartesian(cartesian);
      const longitude = Math.toDegrees(cartographic.longitude);
      const latitude = Math.toDegrees(cartographic.latitude);
      if (pointsEntity.value.length != 0) {
        idNum.value++;
      }

      const point = viewer.entities.add({
        position: cartesian,
        id: 'point' + idNum.value,
        billboard: {
          image: 'src/assets/img/icons/position.png', // 替换为你的图标路径
          width: 32,
          height: 32
        }
      });
      pointsEntity.value.push(point);
      showPopup(longitude, latitude);
    }
  }, ScreenSpaceEventType.LEFT_CLICK);
};
/**
 * 弹窗的展示函数
 * @param longitude
 * @param latitude
 *
 */
function showPopup(longitude: number, latitude: number) {
  const position = Cartesian3.fromDegrees(longitude, latitude);
  const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(position, new Cartesian2());
  if (canvasPosition && popup.value) {
    popupLeft.value = canvasPosition.x - popup.value?.offsetWidth / 2 - 140 - 1632 + 'px';
    popupTop.value = canvasPosition.y - 97 - 170 + 'px';
    popupDisplay.value = 'block';
  }
  // 添加操作完成后恢复鼠标样式为默认箭头
  document.body.style.cursor = 'default';
}
/**
 * 关闭弹窗
 */
function closePopup() {
  popupDisplay.value = 'none';
}
//是否编辑点
const isPointEdit = ref(false);
//编辑的index
const pointEditIndex = ref(-1);
/**
 * 弹窗确认函数
 */
const handleSave = () => {
  let index: number = -1;
  popupDisplay.value = 'none';
  if (isPointEdit.value) {
    popupInfo.value[pointEditIndex.value].name = pointInfo.value.name;
    popupInfo.value[pointEditIndex.value].remark = pointInfo.value.remark;
    index = pointsEntity.value.findIndex(
      (point: { id: any }) => point.id === popupInfo.value[pointEditIndex.value].id
    );
  } else {
    popupInfo.value.push({ ...pointInfo.value, id: 'point' + idNum.value });
    index = pointsEntity.value.findIndex(
      (point: { id: any }) => point.id === 'point' + idNum.value
    );
  }
  pointsEntity.value[index].label = {
    text: pointInfo.value.name,
    pixelOffset: new Cartesian2(0, -30),
    show: true,
    font: '18px sans-serif', // 设置字体大小
    fillColor: Color.AQUA // 设置文本颜色
  };
};

// 创建第二个点击事件处理器:点击已经添加的点执行的内容
const handler2 = new ScreenSpaceEventHandler(viewer.scene.canvas);
handler2.setInputAction(function (event: { position: Cartesian2 }) {
  const pick = viewer.scene.pick(event.position);
  if (pick && pick.id) {
    const index = popupInfo.value.findIndex((point: { id: any }) => point.id === pick.id._id);
    if (index != -1) {
      const cartographic = Cartographic.fromCartesian(pick.primitive._actualPosition);
      const longitude = Math.toDegrees(cartographic.longitude);
      const latitude = Math.toDegrees(cartographic.latitude);
      pointInfo.value = popupInfo.value[index];
      pointEditIndex.value = index;
      isPointEdit.value = true;
      showPopup(longitude, latitude);
    }
  }
}, ScreenSpaceEventType.LEFT_CLICK);

/**
 * 鼠标移入移出实体后提示的显示与隐藏
 */
handler2.setInputAction(function (movement: { endPosition: Cartesian2 }) {
  const pick = viewer.scene.pick(movement.endPosition);
  if (defined(pick) && defined(pick.id)) {
    const index = pointsEntity.value.findIndex((point: { id: any }) => point.id === pick.id._id);
    if (index != -1) {
      const cartesian = viewer.scene.pickPosition(movement.endPosition);

      if (defined(cartesian)) {
        const cartographic = Cartographic.fromCartesian(cartesian);
        const longitude = Math.toDegrees(cartographic.longitude);
        const latitude = Math.toDegrees(cartographic.latitude);
        const position = Cartesian3.fromDegrees(longitude, latitude);
        const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(
          position,
          new Cartesian2()
        );
        if (canvasPosition && tooltip.value) {
          tooltipLeft.value = canvasPosition.x - tooltip.value?.offsetWidth / 2 - 1517 + 'px';
          tooltipTop.value = canvasPosition.y - 59 + 'px';
          tooltipDisplay.value = 'block';
        }
      }
    }
  } else {
    tooltipDisplay.value = 'none';
  }
}, ScreenSpaceEventType.MOUSE_MOVE);

// 创建第三个点击事件处理器:拖拽功能
const dragHandler = new ScreenSpaceEventHandler(viewer.scene.canvas);
dragHandler.setInputAction(function (event: { position: Cartesian2 }) {
  const pickInfo = viewer.scene.pick(event.position);
  if (!pickInfo) {
    return;
  }
  // 如果点击空白区域,则不往下执行
  // 将相机锁定,不然后续移动实体时相机也会动
  viewer.scene.screenSpaceCameraController.enableRotate = false;
  // 为viewer绑定MOUSE_MOVE事件监听器(执行函数,监听的事件)
  dragHandler.setInputAction((movement) => {
    // arg有startPosition与endPosition两个属性,即移动前后的位置信息:Cartesian2对象
    const cartesian = viewer.scene.globe.pick(
      viewer.camera.getPickRay(movement.endPosition)!,
      viewer.scene
    ); //将Cartesian2转为Cartesian3
    const selectedEntity = viewer.entities.getById(pickInfo.id._id); // 实体
    if (!selectedEntity) {
      return false;
    }
    //注意需要赋值三维坐标
    if (cartesian) {
      selectedEntity.position = new ConstantPositionProperty(cartesian);
    }
    // 更新实体位置为当前鼠标位置
  }, ScreenSpaceEventType.MOUSE_MOVE);
  //为viewer绑定LEFT_UP事件监听器(执行函数,监听的事件)
  dragHandler.setInputAction(() => {
    dragHandler.removeInputAction(ScreenSpaceEventType.LEFT_UP);
    dragHandler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE);
    viewer.scene.screenSpaceCameraController.enableRotate = true; // 取消相机锁定
  }, ScreenSpaceEventType.LEFT_UP);
}, ScreenSpaceEventType.LEFT_DOWN);
/**
 * 清空所有标点
 */
const removeAllPoints = () => {
  popupDisplay.value = 'none';
  pointsEntity.value.forEach(function (point: Entity) {
    viewer.entities.remove(point);
  });
  pointsEntity.value.length = 0;
};
/**
 * 根据点的id删除点
 * @param row
 */
const deletePoint = (row: { id: string }) => {
  const index = popupInfo.value.findIndex((point: { id: any }) => point.id === row.id);
  popupInfo.value.splice(index, 1);
  const entityIndex = pointsEntity.value.findIndex((point: { id: any }) => point.id === row.id);
  if (entityIndex !== -1) {
    pointsEntity.value.splice(entityIndex, 1);
    viewer.entities.removeById(row.id);
  }
};
/**
 * 表格点击事件
 * @param row
 */
const handleRow = (row: { id: string }) => {
  const entity = pointsEntity.value.find((point: { id: string }) => point.id === row.id);
  if (entity) {
    const option = Cartographic.fromCartesian(entity._position._value);
    const longitude = Math.toDegrees(option.longitude);
    const latitude = Math.toDegrees(option.latitude);
    const height = Cartographic.fromCartesian(viewer.camera.position).height;
    viewer?.camera.flyTo({
      destination: Cartesian3.fromDegrees(Number(longitude), Number(latitude), height),
      duration: 2
    });
  }
};
/**
 * 监听点数组的变化添加点后移除鼠标左击事件
 */
watch(
  () => pointsEntity,
  () => {
    handlerPoint.value.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
  },
  {
    deep: true
  }
);

onUnmounted(() => {
  dragHandler.removeInputAction(ScreenSpaceEventType.LEFT_DOWN);
  handler2.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE);
  handler2.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
});
</script>
<style lang="scss" scoped>
.my_mark {
  width: 261px;
  min-height: 186px;
  overflow: hidden;
  font-size: 14px;

  .mark_tool {
    display: flex;
    justify-content: space-around;
    align-items: center;
    margin-top: 10px;

    span {
      font-weight: 600;
    }

    .tool_e {
      // width: 16%;
      width: 20%;
      text-align: center;
    }

    .tool_b {
      width: 30px;
      height: 30px;
      border: 1px solid #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
    }

    .tool_f {
      display: flex;
      width: 46%;
      justify-content: space-around;
      align-items: center;
    }

    .tool_d {
      display: flex;
      // width: 32%;
      width: 72%;
      // justify-content: space-around;
      align-items: center;
    }
  }
}

.popover {
  position: absolute;
  width: 310px;
  padding: 2px 10px 10px;
  color: #fff;
  background-color: #3c4f7f;
  border: 1px solid #00effe;

  .header {
    div {
      text-align: right;
    }

    .font {
      text-align: left;
      font-size: 18px;
      margin-bottom: 6px;
      font-weight: 600;
    }

    border-bottom: 1px solid #616161;
  }

  .container {
    margin-top: 10px;
    font-size: 16px;

    .el-row {
      margin-bottom: 10px;
    }
  }

  .btn {
    text-align: center;
  }
}

.Mouse {
  position: absolute;
  padding: 4px;
  font-size: 12px;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.6);
}

.Mouse::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -12px;
  /* 控制三角形的位置 */
  transform: translateY(-50%);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
  border-right: 12px solid rgba(0, 0, 0, 0.6);
  /* 控制三角形的颜色 */
}
:deep(.el-table) {
  background-color: transparent !important;
  color: #fff;
}
:deep(.el-table tr) {
  background-color: transparent !important;
  color: #fff;
}
:deep(.el-table tr:hover) {
  background-color: transparent !important;
}
:deep(.el-table th.el-table__cell) {
  background-color: transparent;
  color: #fff;
}
:deep(.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell) {
  background-color: rgba(0, 0, 0, 0.6);
  color: #fff;
}
:deep(.el-table .cell) {
  background-color: transparent;
  color: #fff;
}
:deep(.el-table__empty-text) {
  color: #fff !important;
}
:deep(.el-table .caret-wrapper) {
  float: right;
  top: 6px;
}
</style>
<style>
.el-popper.is-customized {
  /* Set padding to ensure the height is 32px */
  padding: 6px 12px;
  background: #fff;
}

.el-popper.is-customized .el-popper__arrow::before {
  background: #fff;
  right: 0;
}
</style>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cesium-添加点并且可以编辑 的相关文章

随机推荐

  • MATLAB绘图函数fplot详解

    MATLAB绘图函数fplot详解 一 fplot基本语法 fplot不同于plot 主要用来根据函数表达式和自变量所属区间来直接绘制函数曲线 不需要给出像plot需要给出的自变量和因变量的数组 因此当函数表达式已知的情况 使用fplot绘
  • 倚天服务器里怎么修改装备,倚天私服完整GM命令

    倚天私服完整GM命令 本文出处 网游动力作者 本站发布时间 2009 07 26阅读次数 save命令 save XXX 手动保存玩家数据 save all 手动保存当前地图所有玩家数据 a命令 a ymir 999 调整ymir等级为99
  • 观察者模式和发布订阅模式

    观察者模式与发布订阅模式的区别 1 观察者模式中只有观察者和被观察者 发布订阅模式中有发布者 订阅者 调度中心 2 观察者模式是被观察者发生变化时自己通知观察者 发布订阅模式是通过调度中心来进行分布订阅操作 vue2中响应式数据就是由Obj
  • 【大数据技术】Spark MLlib机器学习特征抽取 TF-IDF统计词频实战(附源码和数据集)

    需要源码和数据集请点赞关注收藏后评论区留言私信 特征抽取 TF IDF TF IDF是两个统计量的乘积 即词频 Term Frequency TF 和逆向文档频率 Inverse Document Frequency IDF 它们各自有不同
  • QT笔记- 对QSring字符串内容进行过滤筛选或对QLineEdi的可输入内容进行控制,使其不含某些字符、只含某些字符或只含特定格式的字符串,如只含字母数字和下划线

    QSring字符串内容的过滤筛选 QString类函数contains 用于判断字符串中是否含有某些字符 其有两个重载函数 第一个是简单筛选 第二个是使用 正则表达式 之后有解释 进行筛选 两函数原型为 bool QString conta
  • protocol buffer 编解码

    平时的开发中使用pb格式协议较多 大致了解了一下pb的编解码 即序列化和反序列化 本文参考官方文档 https developers google com protocol buffers docs encoding hl zh cn 先看
  • Word去除多余的页眉

    word去除多余的页眉 1 在正式页眉开始的页面点击鼠标 此时光标位于要删除页眉下划线页的首部 2 单击上方菜单栏的 页面布局 分隔符 分节符 下一页 3 在正式页眉开始的地方双击鼠标 进入 页眉编辑 状态 4 单击 页眉和页脚 将 链接到
  • SVN时代...

    SourceForge开始全面支持Subversion 这真是个好消息 这预示着CVS独霸天下的时代快要结束 SVN时代就要来临 和CVS比起来 SVN的确很强大 这就像它的出现就是为了取代CVS一样 它的目标快要实现了 具体的功能特性大家
  • Cocos2d-x 3.17.1 Android Studio环境搭建和创建编译项目和真机调试

    eclipse NDK参考 https www cnblogs com l d d p 6531557 html 最近项目上需要用Cocos2d x在Android智能硬件上进行开发 很早之前搭建过Cocos2d x3 15 1 Eclip
  • 利用IDM实现百度云满速下载

    一 IDM Internet Download Manager 简称 IDM 是一种将下载速度提高5倍的工具 可以恢复和安排下载 由于连接丢失 网络问题 计算机关机或意外停电等原因 全面的错误恢复和恢复功能将重新启动中断或中断的下载 简单的
  • MATLAB绘制正弦函数与余弦函数的线性组合曲线

    h0 figure toolbar none position 200 150 450 350 name 实例11 x 0 pi 20 2 pi y1 sin x y2 cos x h1 stem x y1 y2 画出线性组合的图 hold
  • SQL注入——学生选课系统注入

    目录 前言 一 实验环境 二 实验步骤 1 万能密码 2 堆叠注入 3 报错注入 4 时间盲注 前言 本次实验利用教师指定的学生选课管理系统进行SQL注入 包含万能密码登录 堆叠注入 报错注入和时间盲注 一 实验环境 Windows10虚拟
  • QT 15--获取任何种类文件的某些文件属性:大小、创建时间、上次修改时间等等

    1 首先说一些 如果是mainwindow的QT工程 如果打算做自己手写ui 界面的话 该如何将自己写的内容添加到mainwindow界面呢 方法为 新建一个widget类 然后将所有零件都用布局布置好后 只需将总布局添加到widet 然后
  • KMP时间复杂度分析

    比较过程分析 比较次数 比较次数 红色 蓝色 蓝色部分是相比暴力求解 节省下的比较次数 周期 从比较次数可以看出 呈现 1 1 1 1 5 这样的周期 一个周期内的比较次数 8 周期长度 5 周期个数 n 5 比较总次数 周期个数 一个周期
  • 学成在线笔记+踩坑(10)——课程搜索、课程发布时同步索引库。

    导航 黑马Java笔记 踩坑汇总 JavaSE JavaWeb SSM SpringBoot 瑞吉外卖 SpringCloud 黑马旅游 谷粒商城 学成在线 牛客面试题 java黑马笔记 目录 1 检索模块 需求分析 1 1 全文检索介绍
  • H3 GPIO笔记

    NanoPi NEO Core最近买了一块 这个板子使用全志H3 查看H3的数据手册 把GPIO这部分做个笔记 H3有7组GPIO 如下 分别是PA PC PD PE PF PG PL 没有PB这一组 PA有22个端口 PC有19个端口 P
  • 【LeetCode题解】1475、商品折扣后的最终价格

    题目 给你一个数组 prices 其中 prices i 是商店里第 i 件商品的价格 商店里正在进行促销活动 如果你要买第 i 件商品 那么你可以得到与 prices j 相等的折扣 其中 j 是满足 j gt i 且 prices j
  • CSS动画:Transition与Animation

    本文总结CSS3中两个用来做动画的属性 一个是transition 另一个是animation 差异比较 CSS3 差异 transition 在给定的持续时间内平滑地更改属性值 从一个值到另一个值 也就是只需要指定开始与结束的参数 参数改
  • 让汽车的全景环视更智能更安全!

    随着现代汽车安全技术的进步 我们看到诸如全景环视等先进驾驶辅助 ADAS 技术成为现代汽车的新标准 本演示展示了如何通过精确的实时反射和AI来检测障碍 以提升全景环视系统的性能 让汽车驾驶更安全 尤其是 当全景环视系统内嵌Imaginati
  • cesium-添加点并且可以编辑

    完整代码