添加依赖
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":"老龟"
}]
}