Vue + Openlayers入门教程(六):实现信息弹窗功能

信息弹窗功能实现

一、技术栈

Vue 3 + Typescript +Openlayers 7 + Element plus
在这里插入图片描述

二、组件代码

  • OLPopup.vue
<template>
  <div id="popup" class="olPopup" v-show="selectState">
    <a href="#" id="popupCloser" class="olPopupCloser" @click="removePopup"></a>
    <div id="popupContent" v-show="featureAmount > -1">
      <table>
        <tr>
          <th>当前坐标:</th>
          <td>{{ lonAndLat }}</td>
        </tr>
      </table>
      <div v-show="featureAmount > 0">
        <table>
          <tr>
            <th>矢量类型:</th>
            <td>{{ type[layerIndex] }}</td>
          </tr>
          <tr>
            <th>图层名称:</th>
            <td>{{ name[layerIndex] }}</td>
          </tr>
        </table>
        <el-button v-show="featureAmount > 1" @click="changePopup"
          >切换</el-button
        >
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { Feature, Map } from "ol";
import { toLonLat } from "ol/proj";
import Overlay from "ol/Overlay.js";
import bus from "@/utils/bus.ts"; //定义声明文件再引入
import { Coordinate, toStringHDMS } from "ol/coordinate";
import { FeatureLike } from "ol/Feature";
import { Pixel } from "ol/pixel";

let mapCopy: Map;

let popupContainer: HTMLElement;
let popup: Overlay;
let lonAndLat = ref(""); //经纬度
const name = ref<string[]>([]); //图层名称
const type = ref<string[]>([]); //矢量类型
const selectState = ref<boolean>(false); //弹窗状态
let featureAmount = ref<number>(0); //选中矢量要素个数
let layerIndex = ref<number>(0); //图层显示索引

// 添加弹窗
const addPopup = (clickCrd: Coordinate, clickPixel: Pixel) => {
  //获取弹出框DOM
  popupContainer = document.getElementById("popup") as HTMLElement;
  //创建弹出层并绑定DOM
  popup = new Overlay({
    element: popupContainer as HTMLElement,
    autoPan: {
      animation: {
        duration: 250,
      },
    },
  });

  lonAndLat.value = toStringHDMS(toLonLat(clickCrd, "EPSG:4548")); //转换为经纬度坐标
  // 判断点击位置的要素
  let featuresVector: Feature[] = [];
  mapCopy.forEachFeatureAtPixel(clickPixel, (f: FeatureLike) => {
    featuresVector.push(f as Feature);
  });

  featureAmount.value = featuresVector.length; //获取到的元素的个数

  for (let i = 0; i < featureAmount.value; i++) {
    //循环获取元素名称与类型
    name.value.push(featuresVector[i].get("district"));
    type.value.push(featuresVector[i].getGeometry()?.getType() as string);
  }
  mapCopy.addOverlay(popup);
  //设置位置
  popup.setPosition(clickCrd);
};
//关闭弹窗
const removePopup = () => {
  popup.setPosition(undefined);
  selectState.value = false; //关闭弹窗状态
};
//切换要素信息弹窗
const changePopup = () => {
  if (layerIndex.value < featureAmount.value - 1) {
    layerIndex.value++;
  } else {
    alert("已经没有更多图层了");
  }
};

//监听map数据
bus.on("mapToChecked", (res: Map) => {
  // 传参由回调函数中的形参接受
  mapCopy = res;
  //监听click事件
  mapCopy.on("click", (event) => {
    //更新弹窗状态为开启
    selectState.value = true;
    //判断地图实例上是否存在绘制交互,如果存在,关闭弹窗
    mapCopy
      .getInteractions()
      .getArray()
      .some((item) => {
        if (item.getProperties().name === "Draw") {
          selectState.value = false;
        }
      });

    const clickCoordinate: Coordinate = event.coordinate; //获取点击坐标
    const clickPixel: Pixel = event.pixel; //获取点击位置
    featureAmount.value = 0; //每次点击都置空个数
    name.value = []; //置空名称数组
    type.value = []; //置空类型数组
    layerIndex.value = 0; //归零显示图层索引
    addPopup(clickCoordinate, clickPixel); //挂载添加弹窗函数
  });
});
</script>

<style>
.olPopup {
  position: absolute;
  background-color: white;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  bottom: 12px;
  left: -50px;
  min-width: 350px;
}

.olPopup:after,
.olPopup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}

.olPopup:after {
  border-top-color: white;
  border-width: 10px;
  left: 48px;
  margin-left: -10px;
}

.olPopup:before {
  border-top-color: #cccccc;
  border-width: 11px;
  left: 48px;
  margin-left: -11px;
}

.olPopupCloser {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}

.olPopupCloser:after {
  content: "✖";
}
</style>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值