如何实现vue项目中使用Baidu Map,有多个点,鼠标移入出现文字标注,移除消失文字标注,并且点的轨迹连线有箭头指向。

Posted 清风引佩下瑶台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现vue项目中使用Baidu Map,有多个点,鼠标移入出现文字标注,移除消失文字标注,并且点的轨迹连线有箭头指向。相关的知识,希望对你有一定的参考价值。

直接来案例,再分析;

<template>
  <div ref="map" ></div>
</template>

<script>
export default
  data()
    return
      points: [
        lng: 116.404, lat: 39.915, name: \'北京天安门\' ,
        lng: 121.47, lat: 31.23, name: \'上海东方明珠\' ,
        lng: 120.16, lat: 30.25, name: \'杭州西湖\' ,
      ],
      labels: [], // 记录已添加的所有 label 对象
    ;
  ,
  mounted()
    const map = new BMap.Map(this.$refs.map);

    // 循环遍历每一个坐标点,并创建标注对象和文字标注对象
    const polylinePoints = this.points.map((p) => new BMap.Point(p.lng, p.lat)); // 创建用于绘制连线的 BMap.Point 数组
    const polyline = new BMap.Polyline(polylinePoints,
      strokeWeight: 3,
      strokeColor: \'#F00\',
      strokeOpacity: 0.7,
      strokeStyle: \'dashed\',
      enableClicking: false,
      arrowStyle: \'classic\', // 设置箭头标志符号样式
      arrowSize: 12,         // 设置箭头标志符号大小
    );
    map.addOverlay(polyline);

    // 循环遍历每一个坐标点,并创建标注对象和文字标注对象
    for (let i = 0; i < this.points.length; i++)
      const point = new BMap.Point(this.points[i].lng, this.points[i].lat);
      const icon = new BMap.Icon(\'https://lbsyun.baidu.com/jsdemo/img/fox.gif\', new BMap.Size(300, 157));
      const marker = new BMap.Marker(point, icon );
      map.addOverlay(marker);

      // 创建 label 对象
      const label = new BMap.Label(this.points[i].name,
        offset: new BMap.Size(-20, -30),
      );
      marker.addEventListener(\'mouseover\', () =>
        label.setPosition(point); // 设置 label 的地理位置
        map.addOverlay(label);    // 将 label 添加到地图上
        this.labels.push(label);  // 记录已添加的 label 对象
      );
      marker.addEventListener(\'mouseout\', () =>
        map.removeOverlay(label); // 将 label 从地图上移除
        this.labels = this.labels.filter((item) => item !== label); // 从记录中删掉该 label 对象
      );
   

    // 初始化地图控件
    const bounds = new BMap.Bounds(polylinePoints[0], polylinePoints[polylinePoints.length - 1]);
    map.centerAndZoom(bounds.getCenter(), map.getViewport([bounds]).zoom);
    map.enableScrollWheelZoom(true);
  ,
  beforeDestroy()
    const map = this.$refs.map.BMapInstance;
    // 页面销毁时,将所有 label 对象从地图上移除,并清空记录数组
    this.labels.forEach((label) =>
      map.removeOverlay(label);
    );
    this.labels = [];
  ,
;
</script>

这个示例代码中创建了一个包含多个坐标点的数组 points,并在循环遍历每个点时创建了一个 BMap.Marker 标注对象和对应的文字标注 BMap.Label 对象。使用 marker.addEventListener() 方法分别绑定鼠标进入和移出事件,在进入事件回调函数中添加 label 对象到地图中,并记录到数组 labels 中;在移出事件回调函数中从地图上移除 label 对象,并从 labels 数组中删除。

创建连线用于连接多个坐标点,并设置箭头标志样式和大小。

在页面销毁时,通过 beforeDestroy() 钩子函数将所有 label 对象从地图上移除,并清空 labels 数组,以防止内存泄漏。

ps:注意在 Vue 项目中使用 Baidu Map,需要将地图容器 div 挂载到组件 ref 上,并在地图初始化时使用 this.$refs.map.BMapInstance 获取 BMap.Map 对象。

 

但是最后写在项目中的实例。

 

 

以下是实例:

<template>
  <div class="mapTrajectories">
    <div class="queryBox">
      <el-row>
        <div class="lableText">姓名:</div>
        <el-col :span="6">
          <el-select
            size="mini"
            v-model="formDatas.user"
           
            placeholder="请选择"
            filterable
            clearable
            @change="querySearch"
            :filter-method="dataFilter"
          >
            <el-option
              v-for="item in userInfoListFilter"
              :key="item.id"
              :label="item.realname"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-col>
        <div class="lableText">日期:</div>
        <el-col :span="8">
          <el-date-picker
            size="mini"
            v-model="formDatas.time"
            type="daterange"
            range-separator="至"
           
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            format="yyyy-MM-dd"
            value-format="yyyy-MM-dd"
          >
          </el-date-picker>
        </el-col>
        <el-col :span="3">
          <el-button
            size="mini"
            type="primary"
           
            @click="queryMap(false)"
            >查询打卡记录</el-button
          >
        </el-col>
        <el-col :span="3">
          <el-button
            size="mini"
            plain
            type="primary"
           
            :disabled="!formDatas.user"
            @click="queryMap(true)"
            >查询打卡轨迹</el-button
          >
        </el-col>
      </el-row>
    </div>
    <div
      id="allmap"
      ref="map"
      v-loading="loading"
      element-loading-text="拼命加载中"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.5)"
    ></div>
  </div>
</template>

<script>
import mapGetters from "vuex";
import getLocation_clockin from "@/api/business/basicBusiness";
import queryIsLeader from "@/api/business/myApprove";
import queryAllUsers from "@/api/business/index";
import icons from "@/assets/images/location2.png";
export default
  name: "basicBusiness-mapTrajectories",
  components: ,
  data()
    return
      map: null,
      isLeader: false,
      points: [
        lng: 118.80542, lat: 32.039748, name: "南京1" ,
        lng: 118.79542, lat: 32.019748, name: "南京2" ,
        lng: 118.77542, lat: 32.029748, name: "南京3" ,
        lng: 118.60942, lat: 32.049748, name: "南京4" ,
        lng: 118.80942, lat: 32.049748, name: "南京5" ,
      ],
      polyline: null,
      labels: [], // 记录已添加的所有 label 对象
      userInfoList: [], //查询条件--数据状态
      userInfoFilterVal: "", // 筛选字段
      formDatas:
        user: "",
        time: [],
      ,
      loading: false,
      isAddOverlay: false, // 是否显示轨迹
    ;
  ,
  computed:
    ...mapGetters(["userInfo"]),
    userInfoListFilter()
      if (!this.userInfoFilterVal) return this.userInfoList;
      return this.userInfoList.filter((v) =>
        if (v.realname && v.realname.includes(this.userInfoFilterVal))
          return true;
        if (
          v.department &&
          v.department.namePath.includes(this.userInfoFilterVal)
        )
          return true;
        return false;
      );
    ,
  ,
  mounted()
    this.initParams();
    // this.initMap();

    // this.setPointMarkers()
    // this.queryisLeader()
    const myDate = new Date();
    let M = myDate.getMonth() + 1;
    if (M < 10)
      M = "0" + M;
   
    console.log(M, "MMMM");
    //
    this.formDatas.time = [
      // myDate.getFullYear() +\'-\'+ M +"-01",
      myDate.toLocaleDateString().replaceAll("/", "-"),
      myDate.toLocaleDateString().replaceAll("/", "-"),
    ];
    this.queryMap(false);
  ,
  methods:
    initParams()
      let temp = [
        //
        //   id: "all",
        //   realname: "全部",
        // ,
      ];
      //填报人
      queryAllUsers().then((res) =>
        this.$nextTick(() =>
          this.userInfoList = res;
          // this.userInfoList = temp.concat(this.userInfoList); //option--add全部
        );
      );
    ,
    queryMap(isAddOverlay)
      this.isAddOverlay = isAddOverlay;
      this.loading = true;
      let data =
        userid: this.userInfo.user.id, //当前登录用户id
        start:
          this.formDatas.time && this.formDatas.time.length > 0
            ? this.formDatas.time[0]
            : null, //默认当前月
        end:
          this.formDatas.time && this.formDatas.time.length > 0
            ? this.formDatas.time[1]
            : null, //默认当前月

        user: this.formDatas.user, //打卡人员id
      ;
      getLocation_clockin(data).then((res) =>
        if (res.code == "200")
          this.loading = false;
          new Promise((resolve, reject) =>
            this.points = res.data;
            resolve();
          ).then((res) =>
            this.initMap();
          );
       
      );
    ,
    dataFilter(val)
      this.userInfoFilterVal = val;
    ,
    querySearch()
      this.userInfoFilterVal = "";
    ,
    openDrawer()
      this.$refs.detailsDrawer.drawer = true;
    ,
    beforeDestroy()
      this.map = this.map.BMapInstance;
      // 页面销毁时,将所有 label 对象从地图上移除,并清空记录数组
      this.labels.forEach((label) =>
        this.map.removeOverlay(label);
      );
      this.labels = [];
    ,
    initMap()
      this.map = new BMap.Map("allmap");
      this.map.centerAndZoom(
        new BMap.Point(106.34067861392542, 34.129025520059834),
        6
      );
      // 初始化地图控件
      this.map.enableScrollWheelZoom();
      this.map.setMaxZoom(15);
      // 循环遍历每一个坐标点,并创建标注对象和文字标注对象
      for (let i = 0; i < this.points.length; i++)
        const point = new BMap.Point(this.points[i].lng, this.points[i].lat);
        const icon = new BMap.Icon(icons, new BMap.Size(16, 25));
        const marker = new BMap.Marker(point, icon );
        this.map.addOverlay(marker);

        // 创建 label 对象
        const label = new BMap.Label(this.points[i].name,
          offset: new BMap.Size(-20, -30),
        );
        marker.addEventListener("mouseover", () =>
          label.setPosition(point); // 设置 label 的地理位置
          this.map.addOverlay(label); // 将 label 添加到地图上
          this.labels.push(label); // 记录已添加的 label 对象
        );
        marker.addEventListener("mouseout", () =>
          this.map.removeOverlay(label); // 将 label 从地图上移除
          this.labels = this.labels.filter((item) => item !== label); // 从记录中删掉该 label 对象
        );
     

      // 循环遍历每一个坐标点,并创建标注对象和文字标注对象
      const polylinePoints = this.points.map((p) =>
        // console.log(p,\'ppppppppp\');
        return new BMap.Point(p.lng, p.lat);
      ); // 创建用于绘制连线的 BMap.Point 数组
      console.log(polylinePoints, "polylinePoints====", this.points);
      let sy = new BMap.Symbol(BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW,
        scale: 0.5, //图标缩放大小
        strokeColor: "#f00", //设置矢量图标的线填充颜色
        strokeWeight: "1", //设置线宽
      );
      let iconsarrow = new BMap.IconSequence(sy, "0", "20");

      setTimeout(() =>
        let iconDatas = [iconsarrow];
        // 创建箭头标志符号
        const polyline = new BMap.Polyline(polylinePoints,
          strokeWeight: 0.1, //折线的宽度,以像素为单位
          strokeColor: "#F00",
          strokeOpacity: 0.1, //折线的透明度,取值范围0 - 1
          strokeStyle: "dashed",
          icons: iconDatas,
          enableClicking: false,
          arrowStyle: "classic", // 设置箭头标志符号样式
          arrowSize: 2, // 设置箭头标志符号大小
          // strokeOffset: new BMap.Size(-10, 10) // 改变线的位置
          enableEditing: false, //是否启用线编辑,默认为false
          enableClicking: true, //是否响应点击事件,默认为true
        );

        console.log(polyline, "polylineeeeeeeeeee");
        if (this.isAddOverlay)
          this.map.addOverlay(polyline);
       
      , 100);
      // 自动缩放地图,使轨迹全部可视化
      let viewport = this.map.getViewport(this.points);
      this.map.centerAndZoom(viewport.center, viewport.zoom);
    ,
  ,
;
</script>

<style scoped lang="scss">
.mapTrajectories
  position: relative;
  top: 0px;
  bottom: 0;
  width: 100%;

#allmap
  width: 100%;
  height: 100%;
  -webkit-touch-callout: none; /* iOS Safari */
  -webkit-user-select: none; /* Chrome/Safari/Opera */
  -khtml-user-select: none; /* Konqueror */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* Internet Explorer/Edge */
  user-select: none; /* Non-prefixed version, currently not supported by any browser */
.queryBox
  width: 900px;
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 99;
  background: #fff;
  height: 40px;
  line-height: 38px;
  padding: 0px 10px;
  border-radius: 6px;
  .lableText
    width: 60px;
    padding-left: 20px;
    float: left;
 
</style>
 
最后说一下开发中遇到的坑,在绘制点的时候没啥问题,就是大概5000条数据大概8秒钟,1000条还是很快,但是有个问题,坐标点都太近,那就会报错,只要有一个点比较远就能正常,也是很奇怪,排查了问题,最终解决了,此代码就是解决之后的。
文中注释很多,顺便提一下,我这个部门搜索,可根据下拉框中显示的姓名搜索外,还可以根据里面参数搜索。

vue 项目模块化引入百度地图

 

1.1.安装百度地图依赖包

npm i vue-baidu-map --save

2.在src/main.js导入依赖包

import BaiduMap from ‘vue-baidu-map‘

Vue.use(BaiduMap,
ak: ‘YOUR_APP_KEY‘ //这个地方是官方提供的ak密钥
)

技术图片

3.配置地图的基本信息,在我们需要的组件中引用

<!--百度地图-->
<baidu-map class="map"
:center="lng:121.6292529148,lat:31.2035397816"
:zoom=‘13‘
:scroll-wheel-zoom=‘true‘>
<bm-scale anchor="BMAP_ANCHOR_BOTTOM_LEFT"></bm-scale>
<bm-marker :position="lng:121.6292529148,lat:31.2035397816" :dragging="true" animation=‘BMAP_ANIMATION_BOUNCE‘>
<bm-label content=‘上海浦东展讯中心‘ :labelStyle="color:‘red‘,fontSize:‘12px‘" :offset="width:-35,height:30" />
</bm-marker>
</baidu-map>
<Table :columns="columns1" :data="data1"></Table>

技术图片

最终效果如图:

技术图片

 

以上是关于如何实现vue项目中使用Baidu Map,有多个点,鼠标移入出现文字标注,移除消失文字标注,并且点的轨迹连线有箭头指向。的主要内容,如果未能解决你的问题,请参考以下文章

vue 使用百度地图(vue-Baidu-Map)

Vue 实现百度地图(基础)

vue 项目模块化引入百度地图

Vue +ElementUI +Baidu地图 项目模板

vue baidu map之获取选中点的经纬度

使用vue插件实现全球地图,实现你环游世界的梦