vue3+element plus 实现百度地图显示路径

添加依赖

html 复制代码
<!-- index.html -->
    <script type="text/javascript" src="//api.map.baidu.com/getscript?v=3.0&ak=yI6kBeC9G4LntEWXklE2iNHwRUrmFEQc"></script>
    <script type="text/javascript" src="//api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js"></script>
    <script type="text/javascript" src="//api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js"></script>
    <script type="text/javascript" src="//api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script>

实现代码

注意:查询条件使用的自定义组件,不能直接复制使用。点聚合数量多时,页面会卡顿

ts 复制代码
// BaiduMap.vue
<template>
  <div class="content">
    <div id="mapContainer" class="map-container"></div>
    <div class="search-content">
      <div class="header-content" title="点我,点我,点我" @click="handleOpenDrawer">
        <div class="header-image"><Icon icon="ant-design:search-outlined" /></div>
        <!-- <el-image class="header-content-image" :src="openUrl" fit="fill"></el-image> -->
        <div class="header-control">检索</div>
      </div>
    </div>
    <!-- <div class="drawer-content">
        </div> -->
    <el-drawer v-model="drawer" title="详细信息" size="20%" @close="closeDrawer">
      <h-search-form
        :formModel="searchForm.searchModel"
        :formItems="searchForm.searchItems"
        @search="handleSearch"
      />
      <el-divider content-position="left"
        ><h3>{{ personName }}详细行程</h3></el-divider
      >

      <el-timeline>
        <template v-for="(item, index) in timelineData" :key="index">
          <el-timeline-item :timestamp="item.time" placement="top" :color="item.color">
            <el-card>
              <div v-html="item.content" @click="detailed(item.id)" class="point-list"></div>
            </el-card>
          </el-timeline-item>
        </template>
      </el-timeline>
    </el-drawer>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { reactive, toRefs, nextTick } from 'vue'
import request from '@/config/axios'
import { data } from '@/views/Test/map.json'
import hSearchForm from '@/h-components/Form/search-form.vue'
import { HSoft } from '@/utils/hsoft'
import { ElDrawer, ElDivider, ElTimeline, ElTimelineItem, ElCard } from 'element-plus'

const state = reactive({
  ak: 'xxxxxxxxxxxxxxxxxxxx',
  openUrl: new URL('@/assets/imgs/road.png', import.meta.url).href,
  drawer: false,
  searchForm: {
    searchModel: {},
    searchItems: [
      {
        type: 'h-person',
        // label:'人员',
        placeholder: '请输入姓名或工号',
        name: 'senderName',
        defaultValue: '',
        span: 3
      },
      {
        type: 'h-date',
        // label:'创建日期',
        //   placeholder:'请选择日期',
        name: 'createTime',
        valueType: 'daterange',
        defaultValue: '[new Date(2010, 9, 1), new Date(2010, 10, 1)]',
        clearable: true,
        disabled: false,
        startPlaceholder: '开始日期',
        endPlaceholder: '结束日期',
        style: { width: '20%' }
      }
    ]
  },
  map: null,
  timelineData: [],
  personName: '',
  lushu: null,
  polyline: null,
  path: [
    {
      lng: '113.408984',
      lat: '23.174023',
      html: '地点一',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.406639',
      lat: '23.174023',
      html: '地点二',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.403944',
      lat: '23.173566',
      html: '地点三',
      pauseTime: 3,
      name: '叶晨晨'
    },
    {
      lng: '113.400827',
      lat: '23.17394',
      html: '地点四',
      pauseTime: 3,
      name: '叶晨晨'
    },
    {
      lng: '113.397468',
      lat: '23.174496',
      html: '地点五',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.391494',
      lat: '23.174513',
      html: '地点六',
      pauseTime: 4,
      name: '叶晨晨'
    },
    {
      lng: '113.389032',
      lat: '23.174588',
      html: '地点七',
      pauseTime: 3,
      name: '叶晨晨'
    },
    {
      lng: '113.388736',
      lat: '23.173217',
      html: '地点八',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.388511',
      lat: '23.171888',
      html: '地点九',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.388592',
      lat: '23.170501',
      html: '地点十',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.38861',
      lat: '23.170219',
      html: '地点十一',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.38861',
      lat: '23.168342',
      html: '地点十二',
      pauseTime: 2,
      name: '叶晨晨'
    },
    {
      lng: '113.388574',
      lat: '23.165218',
      html: '地点十三',
      pauseTime: 2,
      name: '叶晨晨'
    }
  ]
})

const { searchForm, openUrl, drawer, timelineData, personName } = toRefs(state)

function init() {
  state.map = new BMap.Map('mapContainer')
  const point = new BMap.Point(116.404, 39.915)
  state.map.centerAndZoom(point, 10) //初始化地图,设置中心点坐标和地图级别
  state.map.enableScrollWheelZoom(true) //开启鼠标滚轮缩放
  state.map.addControl(new BMap.NavigationControl())
  state.map.addControl(new BMap.ScaleControl())
  state.map.addControl(new BMap.OverviewMapControl())
  makePolyPoints(state.map, data)

  // request({
  //     url:'@/views/test/map.json',
  //     method:'get'
  // }).then(res =>{
  //     console.log(res);
  //     state.data = res;

  // })
}

function makePolyPoints(map, data) {
  const MAPMarkers = []
  map.clearOverlays()

  data.forEach((point) => {
    const markerPoint = new BMap.Point(point.lng, point.lat)
    const MAPMarker = new BMap.Marker(markerPoint)
    MAPMarker.setTitle(point.name)
    // if (point.type == 'ip') {
    //   // 指定Marker的icon属性为Symbol
    //   const markerIcon = new BMap.Symbol(BMap_Symbol_SHAPE_POINT, {
    //     scale: 1, //图标缩放大小
    //     fillColor: '#f97d1c', //填充颜色
    //     fillOpacity: 0.8 //填充透明度
    //   })
    //   MAPMarker.setIcon(markerIcon)
    // }
    if (point.type == 'ip') {
      // 指定Marker的icon属性为Symbol
      const markerIcon = new BMap.Icon(
      new URL('@/assets/imgs/desktop4.png', import.meta.url).href,
      new BMap.Size(32, 32),
      { anchor: new BMap.Size(16, 16), imageSize: new BMap.Size(32, 32) }
      )
      MAPMarker.setIcon(markerIcon)
    }else{
      const markerIcon = new BMap.Icon(
      new URL('@/assets/imgs/laptop2.png', import.meta.url).href,
      new BMap.Size(32, 32),
      { anchor: new BMap.Size(16, 16), imageSize: new BMap.Size(32, 32) }
      )
      MAPMarker.setIcon(markerIcon)
    }
    //设置marker图标为水滴{

    MAPMarkers.push(MAPMarker)
    // 可以在点对象上添加属性,点击的监听能获取该属性
    // MAPMarker.zbbm = 'xxxxx';
    //信息窗体
    const opts = {
      width: 200,
      height: 120,
      title: point.name + '的位置',
      enableMessage: true
    }
    const sContent =
      '<p>所在位置:' +
      point.lng +
      ', ' +
      point.lat +
      '</p><div class=item-btn οnclick="recentTrips(' +
      point.id +
      ')">最近行程</div>'
    const infoWindow = new BMap.InfoWindow(sContent, opts)
    MAPMarker.addEventListener('click', function (e) {
      map.openInfoWindow(infoWindow, markerPoint)
    })
  })
  if (map.markerClusterer) {
    map.markerClusterer.clearMarkers()
  }
  // 使用点聚合
  map.markerClusterer = new BMapLib.MarkerClusterer(map, {
    markers: MAPMarkers
  })
}

function handleSearch() {
  //  state.drawer = false;
  // var myP1 = new BMap.Point(113.54958146244581,23.131467363279828);    //起点
  // var myP2 = new BMap.Point(116.424374,39.914668);    //终点
  // var myIcon = new BMap.Icon("../assets/icons/car.png", new BMap.Size(32, 70), {    //小车图片
  // 	//offset: new BMap.Size(0, -5),    //相当于CSS精灵
  // 	imageOffset: new BMap.Size(0, 0)    //图片的偏移量。为了是图片底部中心对准坐标点。
  // });
  // var driving2 = new BMap.DrivingRoute(state.map, {renderOptions:{map: state.map, autoViewport: true}});    //驾车实例
  // driving2.search(myP1, myP2);    //显示一条公交线路

  state.timelineData = [
    {
      time: '2018/4/12',
      content: '<h4>Update Github template</h4><p>Tom committed 2018/4/12 20:46</p>',
      color: '#0bbd87',
      id: 30
    },
    {
      time: '2018/4/3',
      content: '<h4>Update Github template</h4><p>Tom committed 2018/4/3 20:46</p>',
      color: '#cf4813',
      id: 31
    },
    {
      time: '2018/4/2',
      content: '<h4>Update Github template</h4><p>Tom committed 2018/4/2 20:46</p>',
      color: '#f0d695',
      id: 32
    }
  ]

  state.personName = '乔蓦然'

  // // 创建polyline对象
  makePolyPoints(state.map, state.path)
  const centerPoint = new BMap.Point(state.path[0].lng, state.path[0].lat)
  state.map.centerAndZoom(centerPoint, 17) //初始化地图,设置中心点坐标和地图级别
  makePolyline(state.path)
  makeLushu(HSoft.deepClone(state.path))
}

function makePolyline(path) {
  let point = []
  path.forEach((item) => {
    point.push(new BMap.Point(item.lng, item.lat))
  })
  //轨迹显示样式
  const sy = new BMap.Symbol(BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW, {
    scale: 0.6, //图标缩放大小
    strokeColor: '#fff', //设置矢量图标的线填充颜色
    strokeWeight: '2' //设置线宽
  })
  const icons = new BMap.IconSequence(sy, '10', '30')

  state.polyline = new BMap.Polyline(point, {
    enableEditing: false, //是否启用线编辑,默认为false
    enableClicking: true, //是否响应点击事件,默认为true
    strokeColor: '#18a45b', //折线颜色
    strokeWeight: 8, //折线的宽度,以像素为单位
    strokeOpacity: 0.5, //折线的透明度,取值范围0 - 1
    icons: [icons]
  }) //创建折线
  state.map.addOverlay(state.polyline) //增加折线
}

function makeLushu(path) {
  let point = []
  path.forEach((item) => {
    point.push(new BMap.Point(item.lng, item.lat))
  })
  state.lushu = new BMapLib.LuShu(state.map, point, {
    defaultContent: '坐车车', //默认显示
    autoView: true, //是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
    icon: new BMap.Icon(
      new URL('@/assets/imgs/map-user.png', import.meta.url).href,
      new BMap.Size(32, 32),
      { anchor: new BMap.Size(16, 32), imageSize: new BMap.Size(32, 32) }
    ),
    speed: 4500,
    enableRotation: false, //是否设置marker随着道路的走向进行旋转
    landmarkPois: path
  })

  state.lushu.start()
}

function handleOpenDrawer() {
  state.drawer = true
}

const recentTrips = (id) => {
  console.log('近期行程')
  handleOpenDrawer()
  state.map.closeInfoWindow()
  handleSearch()
}

function closeDrawer() {
  console.log('关闭')
  makePolyPoints(state.map, data)
  state.personName = ''
  state.timelineData = []
}

function detailed(point) {
  let points = []
  switch (point) {
    case 30:
      points.push({ lng: '113.388511', lat: '23.171888', id: 30, name: '叶晨晨' })
      break
    case 31:
      points.push({ lng: '113.38861', lat: '23.168342', id: 30, name: '叶晨晨' })
      break
    case 32:
      points.push({ lng: '113.400827', lat: '23.17394', id: 30, name: '叶晨晨' })
      break
  }
  makePolyPoints(state.map, points)
  const centerPoint = new BMap.Point(points[0].lng, points[0].lat)
  state.map.centerAndZoom(centerPoint, 17) //初始化地图,设置中心点坐标和地图级别
  makePolyline(state.path)
}

onMounted(() => {
  nextTick(() => {
    init()
  })
  window.recentTrips = recentTrips
})
</script>

<style lang="less" scoped>
.map-container {
  height: calc(100vh - 84px - 40px);
}

:deep(.el-overlay) {
  width: 20%;
  position: unset;
}
.search-content {
  position: absolute;
  top: 22px;
  right: 22px;

  .header-content {
    cursor: pointer;
    background: #fff;
    padding-right: 12px;
    padding-left: 12px;
    display: flex;
    align-items: center;
    .header-image {
      width: 25px;
    }

    .header-control {
      font-size: 12px;
      line-height: 34px;
    }
  }
}
:deep(img) {
  max-width: inherit;
}
:deep(.item-btn) {
  cursor: pointer;
  color: #409eff;
}
:deep(.el-timeline) {
  padding-left: 0px;
}

:deep(.BMap_bubble_content) {
  overflow: auto;
  height: 90px;
}

.point-list {
  cursor: pointer;
}
</style>

坐标数据

json 复制代码
// map.json
{
    "data":[{
        "id":1,
        "lng":"116.404",
        "lat":"39.925",
        "type":"ip",
        "name":"乔乔"
    },{
        "id":2,
        "lng":"116.404",
        "lat":"39.915",
        "type":"ip",
        "name":"孙悟空"
    },{
        "id":3,
        "lng":"116.395",
        "lat":"39.935",
        "name":"唐僧"
    },{
        "id":4,
        "lng":"116.415",
        "lat":"39.931",
        "type":"ip",
        "name":"观音菩萨"
    },{
        "id":5,
        "lng":"111.404",
        "lat":"38.925",
        "name":"土地公公"
    },{
        "id":6,
        "lng":"110.404",
        "lat":"31.925",
        "type":"ip",
        "name":"白龙马"
    },{
        "id":7,
        "lng":"113.384",
        "lat":"24.925",
        "name":"猪八戒"
    },{
        "id":8,
        "lng":"113.404",
        "lat":"23.925",
        "name":"太白金星"
    },{
        "id":9,
        "lng":"112.434",
        "lat":"39.925",
        "name":"沙悟净"
    },{
        "id":10,
        "lng":"116.414",
        "lat":"38.915",
        "name":"哪吒"
    },{
        "id":11,
        "lng":"116.404",
        "lat":"37.925",
        "name":"金毛吼"
    },{
        "id":12,
        "lng":"117.404",
        "lat":"39.925",
        "name":"嫦娥"
    },{
        "id":13,
        "lng":"116.404",
        "lat":"38.925",
        "name":"太上老君"
    },{
        "id":14,
        "lng":"114.404",
        "lat":"38.925",
        "name":"铁扇公主"
    },{
        "id":15,
        "lng":"111.404",
        "lat":"30.925",
        "name":"牛魔王"
    },{
        "id":16,
        "lng":"115.404",
        "lat":"39.915",
        "name":"红孩儿"
    },{
        "id":17,
        "lng":"115.404",
        "lat":"30.925",
        "name":"清风"
    },{
        "id":18,
        "lng":"118.404",
        "lat":"31.925",
        "name":"明月"
    },{
        "id":19,
        "lng":"117.404",
        "lat":"32.925",
        "name":"女儿国王"
    },{
        "id":20,
        "lng":"116.304",
        "lat":"39.825",
        "name":"白骨精"
    },{
        "id":21,
        "lng":"116.404",
        "lat":"39.725",
        "name":"蜘蛛精"
    },{
        "id":22,
        "lng":"116.504",
        "lat":"39.925",
        "name":"孔雀公主"
    },{
        "id":23,
        "lng":"116.414",
        "lat":"39.914",
        "name":"大鹏鸟"
    },{
        "id":24,
        "lng":"116.400",
        "lat":"39.920",
        "name":"老龟"
    }]
}
相关推荐
乐闻x39 分钟前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
许苑向上1 小时前
Dubbo集成SpringBoot实现远程服务调用
spring boot·后端·dubbo
大力财经2 小时前
百度Q3财报:净利润增长17%超预期 文心大模型日调用量增30倍达15亿
百度
533_2 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
请叫我雷轰2 小时前
百度主动推送可以提升抓取,它能提升索引量吗?
百度·dubbo
陪学2 小时前
百度遭初创企业指控抄袭,维权还是碰瓷?
人工智能·百度·面试·职场和发展·产品运营
ZBY520313 小时前
【Vue】 npm install amap-js-api-loader指南
javascript·vue.js·npm
计算机毕设指导63 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
qdprobot3 小时前
ESP32桌面天气摆件加文心一言AI大模型对话Mixly图形化编程STEAM创客教育
网络·人工智能·百度·文心一言·arduino
木子02044 小时前
前端VUE项目启动方式
前端·javascript·vue.js