vue3+element=plus 高德地图路径巡航根据经纬度动态设置巡航路径
代码片段
<template>
<div style="width: 100%;height: 100vh;position: relative">
<div v-show="!data.isDes"
style="position: absolute;left: 0;top: 0;bottom: 0;z-index: 99999;display: flex;flex-direction: row;align-items: center;justify-content: center">
<div :class="['box', slideClass]" style="height: 100%">
<div style="background: #fff;height: 100%;flex: 1;display: flex;flex-direction: column">
<div style="padding: 10px">
<!-- <el-input-->
<!-- v-model="formData.keyword"-->
<!-- placeholder="车牌号/姓名/电话/车辆位置"-->
<!-- >-->
<!-- <template #prepend>-->
<!-- <el-select v-model="formData.select" placeholder="Select" style="width: 106px;" size="large">-->
<!-- <el-option label="全部(99)" value="0"/>-->
<!-- <el-option label="行驶(99)" value="1"/>-->
<!-- <el-option label="离线" value="2"/>-->
<!-- <el-option label="禁止" value="3"/>-->
<!-- </el-select>-->
<!-- </template>-->
<!-- </el-input>-->
</div>
<div style="display: flex;flex-direction: row;align-items: center;padding: 4px 10px">
<div style="display:flex;flex-direction: row;align-items: center">
<div class="circle" />
<span>空闲中</span>
</div>
<div style="display:flex;flex-direction: row;align-items: center;margin-left: 8px">
<div class="circleRed" />
<span>任务中</span>
</div>
</div>
<div style="width: 95%;height: 100%;">
<recursive-menu :menu-items="menu.list"></recursive-menu>
</div>
</div>
</div>
<div style="margin-left: -24px" @click="toggle">
<div :class="['icon', data.show ? 'arrow-up' : 'arrow-down']">
<img src="/static/icon_location_close.png" style="width: 50px;height: 50px">
</div>
</div>
</div>
<div v-show="data.isDes" style="position: absolute;left: 30px;top: 30px;z-index: 999999">
<el-button type="primary" plain @click="closeDes">关闭轨迹</el-button>
</div>
<el-row>
<el-col :span="24">
<div class="grid-content ep-bg-purple-dark" />
<div style="height: 100vh" id="container" ref="map"></div>
</el-col>
</el-row>
<el-dialog v-model="data.dialogVisible" title="Tips" width="30%">
<div style="display: flex;flex-direction: column">
<el-form label-position="top" label-width="100px" style="max-width: 460px">
<el-form-item label="起始日期">
<el-date-picker v-model="formData.startDate" type="date" label="起始日期" placeholder="起始日期"
style="width: 100%" />
</el-form-item>
<el-form-item label="开始时间">
<el-time-picker v-model="formData.startTime" label="开始时间" placeholder="开始时间"
style="width: 100%" />
</el-form-item>
<el-form-item label="截至日期">
<el-date-picker v-model="formData.startDate" type="date" label="截至日期" placeholder="截至日期"
style="width: 100%" />
</el-form-item>
<el-form-item label="结束时间">
<el-time-picker v-model="formData.endTime" label="结束时间" placeholder="结束时间"
style="width: 100%" />
</el-form-item>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="data.dialogVisible = false">关闭</el-button>
<el-button type="primary" @click="handleClose">
查看轨迹
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import RecursiveMenu from '../../components/RecursiveMenu.vue';
import {
reactive,
computed,
ref,
watch,
getCurrentInstance
} from 'vue';
import {
ElMessage
} from 'element-plus'
const {
proxy
} = getCurrentInstance()
import {
useRouter
} from 'vue-router'
const router = useRouter();
const handleClose = () => {
console.log(1112222)
data.dialogVisible = false
console.log(routeList[0])
data.isDes = true
pathSimplifierIns.setData([routeList[0]]);
}
function closeDes() {
doExpand()
data.isDes = false
}
function handleBtn1Click() {
console.log(1111)
data.dialogVisible = true
InfoWindow.close()
}
function handleBtn2Click() {
console.log(22222)
InfoWindow.close()
}
function handleBtn3Click() {
console.log(33333)
InfoWindow.close()
}
const formData = reactive({
keyword: '',
select: '0',
startDate: '2023-12-14',
startTime: new Date(2023, 12, 14, 0, 0),
endDate: '2023-12-14',
endTime: new Date(2023, 12, 14, 23, 59),
});
const data = reactive({
dialogVisible: false,
show: true,
isDes: false,
socket:null,
});
const menu = reactive({
list: [{
type: 'err',
name: '离线车辆1'
},
{
type: 'warring',
name: '静止车辆2'
},
{
type: 'success',
name: '运动车辆2'
},
{
type: 'success',
name: '运动车辆2'
}
]
});
const slideClass = computed(() => {
return data.show ? 'slide-enter-active' : 'slide-enter';
});
const toggle = () => {
console.log(1112222)
data.show = !data.show;
};
let InfoWindow = null
window.AMapLoader.load({
"key": "",
"version": "2.0",
"plugins": ['AMap.Scale'],
"AMapUI": {
"version": '1.1',
"plugins": ['overlay/SimpleMarker', 'misc/PathSimplifier'],
},
"Loca": {
"version": '2.0'
},
}).then((AMap) => {
var map = new AMap.Map('container');
map.addControl(new AMap.Scale());
InfoWindow = new window.AMap.InfoWindow
aaaa(map)
}).catch((e) => {
console.error(e);
});
let routeList = []
let newRouteList = []
let navgList = []
let markerList = []
let pathSimplifierIns = null
let newObjList = []
let endIdx = 0
function aaaa(map) {
console.log(window.AMapUI)
var pathNavigatorStyle = {
initRotateDegree: 0,
width: 16,
height: 16,
autoRotate: true,
lineJoin: 'round',
content: 'defaultPathNavigator',
fillStyle: '#087EC4',
strokeStyle: '#116394',
lineWidth: 1,
pathLinePassedStyle: {
lineWidth: 0,
strokeStyle: 'rgba(8, 126, 196, 1)',
borderWidth: 0,
borderStyle: '#eeeeee',
dirArrowStyle: false
}
}
pathSimplifierIns = new window.AMapUI.PathSimplifier({
zIndex: 0,
autoSetFitView: true,
map: map,
getPath: function(pathData) {
return pathData.path;
},
getHoverTitle: function(pathData, pathIndex, pointIndex) {
if (pointIndex >= 0) {
return pathData.name + ',点:' + pointIndex + '/' + pathData.path.length;
}
return pathData.name + ',点数量' + pathData.path.length;
},
renderOptions: {
pathNavigatorStyle: pathNavigatorStyle,
renderAllPointsIfNumberBelow: 100
}
})
window.pathSimplifierIns = pathSimplifierIns;
fetch('https://a.amap.com/amap-ui/static/data/big-routes.json')
.then(response => response.json())
.then(routeData => {
routeList = routeData
for (let i = 0, len = routeData.length; i < len; i++) {
let newItem = {
name: routeList[i].name,
path: routeList[i].path.slice(endIdx, 1)
}
newRouteList.push(newItem)
}
pathSimplifierIns.setData(newRouteList);
for (let i = 0, len = newRouteList.length; i < len; i++) {
navgList[i] = pathSimplifierIns.createPathNavigator(0, {
loop: true,
speed: 54
});
let markerContent = `
<div style="display: flex;flex-direction: row;white-space: nowrap;background: #fff;border: 1px solid #000;border-radius: 4px;padding: 2px">
<div style="display:flex;flex-direction: row;align-items: center;margin-left: 8px;font-size: 12px">
<span>运动车辆-模拟司机7-54Km/h-22.12</span>
</div>
</div>`
let newMarler = new window.AMap.Marker({
clickable: true,
anchor: 'bottom-center',
position: new window.AMap.LngLat(newRouteList[i].path[0][0], newRouteList[i].path[0][
1]),
content: markerContent,
extData: {
pathIndex: i
}
});
newMarler.on('click', (e) => {
let infoContent = `
<div style="display: flex;flex-direction: column;padding: 5px">
<div style="text-align: center">详情</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;font-size: 14px">当前位置: 山东省青岛市************************</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;font-size: 14px">司机信息: 模拟司机4•</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;font-size: 14px">车牌号: 运动车辆7</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;font-size: 14px">定位时间: 2023-12-13 05:39:33</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;font-size: 14px">车辆状态: 行驶中 (46km/h)•油量 (66.6L)</div>
<div style="display: flex;flex-direction: row;align-content: center;padding: 6px 2px;justify-content: space-around;margin-top: 20px">
<button οnclick="btn1()" id="btn1" style="flex: 1;margin-right: 10px;padding: 6px 0;border: 1px solid #007bff;background: #fff;border-radius: 4px">查看轨迹</button>
<button οnclick="btn2()" id="btn4" style="flex: 1;margin-right: 10px;padding: 6px 0;border: 1px solid #007bff;background: #fff;border-radius: 4px">关闭</button>
</div>
</div>
`
InfoWindow.setContent(infoContent);
InfoWindow.open(map, e.target.getPosition());
console.log(e.target.getExtData())
});
window.btn1 = () => {
handleBtn1Click()
}
window.btn2 = () => {
handleBtn2Click()
}
window.btn3 = () => {
handleBtn3Click()
}
map.add(newMarler)
markerList[i] = newMarler
navgList[i].start()
}
console.log(pathSimplifierIns.getPathNavigators())
if (doExpand()) {
setInterval(() => {
console.log(data)
if (!data.isDes) {
console.log(111111)
doExpand()
}
}, 2000)
}
})
}
function onload() {
pathSimplifierIns.renderLater();
}
function doExpand() {
if (!data.isDes) {
newObjList = []
const objectList = pathSimplifierIns.getPathNavigators()
for (let i = 0; i < objectList.length; i++) {
newObjList.push({
cursor: JSON.parse(JSON.stringify(objectList[i].getCursor())),
status: objectList[i].getNaviStatus()
})
}
}
endIdx++;
for (let i = 0; i < navgList.length; i++) {
newRouteList[i].path = routeList[i].path.slice(0, endIdx + 1);
}
pathSimplifierIns.setData(newRouteList);
for (let i = 0; i < navgList.length; i++) {
navgList[i] = pathSimplifierIns.createPathNavigator(i, {
speed: 54,
pathNavigatorStyle: {
width: 16,
height: 32,
content: window.AMapUI.PathSimplifier.Render.Canvas.getImageContent('/static/carRed.png',
onload, onerror),
strokeStyle: null,
fillStyle: null
},
});
navgList[i].on('move', function() {
markerList[i].setPosition(navgList[i].getPosition());
});
if (newObjList[i].status !== 'stop') {
navgList[i].start();
}
if (newObjList[i].cursor.idx >= 0) {
navgList[i].moveToPoint(newObjList[i].cursor.idx, newObjList[i].cursor.tail);
}
}
return true;
}
data.socket = new WebSocket('ws://192.168.3.40:8080/sockjs-node/160/10aoqxi4/websocket')
data.socket.addEventListener('open', () => {
console.log('WebSocket connected')
})
</script>
<style scoped>
.box {
overflow: hidden;
transition: width 0.5s;
}
.slide-enter,
.slide-leave-to {
width: 0;
}
.slide-enter-active,
.slide-leave-active {
width: 500px;
}
.icon {
display: inline-block;
width: 50px;
height: 50px;
transition: transform 0.3s;
}
.arrow-up {
transform: rotate(180deg);
}
.arrow-down {
transform: rotate(0deg);
}
.circle {
width: 11px;
height: 11px;
border: 3px solid #28a745;
border-radius: 50%;
position: relative;
background-color: white;
}
.circle::before {
content: "";
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
background-color: #28a745;
border-radius: 50%;
}
.circleRed {
width: 11px;
height: 11px;
border: 3px solid #dc3545;
border-radius: 50%;
position: relative;
background-color: white;
}
.circleRed::before {
content: "";
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
background-color: #dc3545;
border-radius: 50%;
}
</style>