vue3 在线引入天地图,点标记、序号label、最佳显示区域

由于百度地图后端接口某些东西开始收费,地图组件就换成了天地图。

和使用百度地图实现差别不是太大,就是api接口需要改变,一开始没找到最佳显示区域的api,我以为会消耗很长的时间,今天找了找 发现有这个api

<template>
  <div class="contain">
    <div id="allmap">
    </div>
    <div class="legendBox" v-show="props.showLegend">
      <template v-for="item in addressMap" :key="item.value">
        <div class="legendBox-item" v-if="!item.hidden">
          <img :src="item.icon" :alt="item.label" />
          <span class="legendBox-item-word">{{ item.label }}</span>
        </div>
      </template>
    </div>

  </div>
</template>

<script setup>
import bluePeople from "@/assets/blue-robot.png";
import houseIcon from "@/assets/map/house.png";
import peperIcon from "@/assets/map/peper.png";
import projectIcon from "@/assets/map/project.png";
import connectIcon from "@/assets/map/connect.png";
import shadowIcon from "@/assets/map/shadow.png";
import gasIcon from "@/assets/map/gas.png";
import chooseIcon from "@/assets/map/isChoose.png";
const addressMap = [];//图例
const props = defineProps({
  heat: {
    type: Array,
    default: () => [],
  },
  maker: {
    type: Array,
    default: () => [],
  },
  seMarker: {
    type: Number,
    default: 0,
  },
  showLegend: {
    type: Boolean,
    default: true,
  },
  zoom: {
    type: Number,
    default: 0,
  }
});

let map = null;
// 初始化地图
const initMap = () => {
  nextTick(() => {
    map = new T.Map("allmap",{ // allmap必须和dom上的id一直
      minZoom: 3,
      maxZoom: 20
    });
    // map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 4);
    //创建缩放平移控件对象
    var control = new T.Control.Zoom();
    //添加缩放平移控件
    map.addControl(control);
  })
};


onMounted(initMap);

const makerList = ref([]);
const infoWindowList = ref([]);
const createIcon = (type) => {
  return new T.Icon({
    iconUrl: addressMap.find((c) => c.value === type)?.icon || peperIcon,
    iconSize: new T.Point(30, 30),
  })
};
const createMaker = (val) => {
  if (makerList.value.length) {
    map.clearOverLays();
    makerList.value = [];
    infoWindowList.value = [];
  }
  val.forEach((item) => {
    const label = item.condition.split("_").join("<br />");
    var pt = new T.LngLat(item.position[0], item.position[1]);
    var infoWindow = new T.InfoWindow(label,{
      offset: new T.Point(0, -16) //解决mouseover - mouseout事件 信息窗口闪动问题
    });
    infoWindowList.value.push(infoWindow)
    // 图标序号标记
    if (item.num) {
      const numLabel = new T.Label({
        text: `<div class='numLabel'>${item.num}</div>`,
        position: pt,
        offset: new T.Point(-20, 5)
      });
      const wordTip = new T.Icon({
        iconUrl: peperIcon,
        iconSize: new T.Point(30, 30),
      })
      const wordMarker = new T.Marker(pt, { icon: wordTip })
      makerList.value.push(wordMarker);
      map.addOverLay(wordMarker);
      map.addOverLay(numLabel);
      numLabel.addEventListener("mouseover", function(){
        wordMarker.openInfoWindow(infoWindow, pt);
      });
      numLabel.addEventListener("mouseout", function(){
        wordMarker.closeInfoWindow(infoWindow, pt);
      });
    } else {
      // 图标标记
      const icon = createIcon(item.type);
      const marker = new T.Marker(pt, { icon });
      makerList.value.push(marker);
      map.addOverLay(marker);
      marker.addEventListener("mouseover", function(){
        marker.openInfoWindow(infoWindow, pt);
      });
      marker.addEventListener("mouseout", function(){
        marker.closeInfoWindow(infoWindow, pt);
      });
    }
  });
  setViewport(makerList.value)
};
watch(() => props.maker, createMaker);
/**
 * 使用BMap.Viewport来获取这些点的最佳显示视图
 * @param {*} markers 标点集合
 */
const setViewport = (markers) => {
  if(markers.length == 0) return; //这个地方会加载两次 不清楚为啥,所以使用if过滤掉空的情况
  var points = markers.map(function(marker) {
    return marker.getLngLat(); // 此处获取每个标记的地理位置点
  });

  var view = map.getViewport(points); // 计算这些点的最佳视图
  var mapZoom = view.zoom;
  var centerPoint = view.center;
  if(props.zoom != 0) {//单点标记时候展示地标
    mapZoom = props.zoom
  }
  map.centerAndZoom(centerPoint,mapZoom); // 动态更新地图的中心点和Zoom级别
}
/**
 * @param {*} seq 序号,表格单击选择和取消选择的infowindow展示和关闭
 */
const dispatchMarker = (seq) => {
  if (makerList.value.length) {
    // 关闭所有信息窗口
    makerList.value.forEach((marker,idx) => marker.closeInfoWindow(infoWindowList.value[idx]));
    // 打开选定的信息窗口
    if(seq > 0) {
      const selectedMarker = makerList.value[seq - 1];
      selectedMarker.openInfoWindow(infoWindowList.value[seq - 1],selectedMarker.getLngLat());
    }
  }
};
watch(() => props.seMarker, dispatchMarker);
</script>

<style lang="scss" scoped>
.contain {
  width: 100%;
  height: 100%;
  position: relative;
  #allmap {
    width: 100%;
    height: 100%;
    position: relative;
    :deep(.tdt-control-copyright.tdt-control) {
      display: none !important;
    }
    :deep(.tdt-overlay-pane) {
      z-index: 620;
      cursor: pointer;
      .tdt-label {
        width: 0;
        padding: 0;
        border: none;
      }
      .numLabel {
        width: 16px;
        height: 16px;
        line-height: 16px;
        text-align: center;
        border-radius: 50%;
        background-color: #fff;
      }
    }
  }
  .legendBox {
      width: 150px;
      padding: 10px;
      font-size: 14px;
      background: rgba(255, 255, 255, 0.8);
      position: absolute;
      right: 10px;
      bottom: 10px;
      z-index: 1002;
      border-radius: 11px;
      &-item {
        height: 30px;
        display: flex;
        align-items: center;
        margin-bottom: 10px;
        img {
          height: 100%;
        }
      }
    }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值