1.地图导航,描点弹窗信息窗口,鼠标移上高亮图标,支持组件外元素高亮activeMark(传入对应数据即可),关闭高亮activeClose
<!----地图组件---司机位置及描点 信息窗口--->
<!---
API说明 非必填
list 导航数组 [[121.488697,31.259303],[121.488697,31.289303]]
list[0] 数组 起始坐标 [121.488697,31.259303]
list[1] 数组 终点坐标 [121.488697,31.289303]
motormanList 司机数组 地图标注司机位置 点击展示司机信息
licensePlate 车牌号
name 司机姓名
status 司机状态
time 希望到达时长
end 下班时间
serviceList 服务商数组
---->
<template>
<div id="app">
<div id="container"></div>
<div id="panel"></div>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import red from "@/assets/red.png";
import success from "@/assets/success.png";
import yellow from "@/assets/yellow.png";
import cart from "@/assets/cart.png";
import destination from "@/assets/destination.png";
import rescue from "@/assets/rescue.png";
import active from "@/assets/active.png";
import service1 from "@/assets/service1.png";
import service2 from "@/assets/service2.png";
export default {
props:["list","motormanList","serviceList"],
name: 'Xmaps',
data(){
return {
icon:[red,success,yellow,cart],
// motormanList:[
// {licensePlate:"沪A54564",name:"刘xxx",status:0,time:20,end:"14:20",position:[121.488697,31.259303]},
// {licensePlate:"沪A59874",name:"王xxx",status:1,time:20,end:"14:30",position:[121.488697,31.289303]},
// ]
map:"",
driving:"",
startMarker:[],
startMarkerIcon:[],
serviceMarkerIocn:[],
marker:"",
marker1:"",
serviceMarker:""
}
},
destroyed(){
this.map.destroy();
},
methods:{
...mapActions([]),
//创建信息窗口--司机
info(data){
if(!data){
return false;
}
var self = this;
var temp = "";
var infoWindow;
var cartName = [],sjName=[];
data.car_id.map((e)=>{
cartName.push(e.name);
})
data.s_id.map((e)=>{
sjName.push(e.name);
})
temp = `<div style="font-size:12px;color:#222;width:160px;padding:10px">
<div style="line-height:24px;">
<label style="margin-right:10px;">车牌号</label>
<span style="color:#909399">${data.license_plate?data.license_plate:'无'}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">救援司机</label>
<span style="color:#909399">${data.name}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">服务商</label>
<span style="color:#909399">${data.service_name}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">手机号</label>
<span style="color:#909399">${data.mobile}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">车辆状态</label>
<span style="color:${data.ready==0?'#00C80C':(data.ready==1?'#FB0000':"#FF9C00")}">${data.ready==0?'空闲':(data.ready==1?'进行中':"休息")}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">车辆类型</label>
<span style="color:#909399">${cartName.length>0?cartName.join(','):"无"}</spam>
</div>
<div style="line-height:24px">
<label style="margin-right:10px;">司机技能</label>
<span style="color:#909399">${sjName.length>0?sjName.join(','):"无"}</spam>
</div>
</div>`;
var info = [];
info.push(temp);
infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(-10, -30),
content: info.join("") //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(this.map,data.position);
},
//创建点坐标---司机
point(){
// 将 icon 传入 marker
this.map.remove(this.startMarker);
this.map.remove(this.startMarkerIcon);
this.startMarker = [];
this.startMarkerIcon = [];
if(this.motormanList.length>0){
this.motormanList.map((data,inx)=>{
var img = "";
if(data.ready==1){
img = this.icon[1];
}else if(data.ready==2){
img = this.icon[2];
}else{
img = this.icon[0];
}
// if(data.selected){
// img = active;
// }
var html = `<div style='width:100px;text-align:center;font-size:12px;color:#fff;background:rgba(0,0,0,0.8);padding:2px 10px;border-radius:5px;line-height:24px;'>${data.license_plate?data.license_plate:'无'}</div>`;
var startMarkerIcon = new AMap.Marker({
position: new AMap.LngLat(data.position[0]-0,data.position[1]-0),
icon: img,
topWhenClick:true,
zIndex:100,
offset: new AMap.Pixel(-30, -30)
});
var startMarker = new AMap.Marker({
position: new AMap.LngLat(data.position[0]-0,data.position[1]-0),
content: html,
topWhenClick:true,
zIndex:100,
offset: new AMap.Pixel(-60, 18)
});
this.startMarker.push(startMarker);
this.startMarkerIcon.push(startMarkerIcon);
var self = this;
startMarkerIcon.on("click",function(){
self.$emit("rowClick",{
name:"motormanList",
data:data
});
self.info(data);
})
startMarkerIcon.on("mouseover",function(el){
self.activeMark(inx,data,1);
})
startMarkerIcon.on("mouseout",function(el){
self.activeClose(inx,data);
})
})
// 将 markers 添加到地图
this.map.add(this.startMarker);
this.map.add(this.startMarkerIcon);
this.map.setZoomAndCenter(14,this.motormanList.length>0?this.motormanList[0].position:this.list[0]);
this.info(this.motormanList[0]);//默认显示第一个
}
},
//高亮节点图标
activeMark(inx,row,type){
this.startMarkerIcon[inx].setIcon(active);
this.startMarkerIcon[inx].setzIndex(110);
this.info(row);
if(type!=1){
//this.map.setCenter(row.position);
}
},
//关闭高亮
activeClose(inx,row){
var img = "";
if(row.ready==1){
img = this.icon[1];
}else if(row.ready==2){
img = this.icon[2];
}
this.startMarkerIcon[inx].setIcon(img);
this.startMarkerIcon[inx].setzIndex(100);
this.map.clearInfoWindow();
},
activeMarkSer(inx,row,type){
this.serviceMarkerIocn[inx].setIcon(service2);
this.serviceMarkerIocn[inx].setzIndex(110);
this.serviceInfo(row);
if(type!=1){
//this.map.setCenter([row.lng,row.lat]);
}
},
activeCloseSer(inx,row){
this.serviceMarkerIocn[inx].setIcon(service1);
this.serviceMarkerIocn[inx].setzIndex(100);
this.map.clearInfoWindow();
},
//创建服务商信息窗口
serviceInfo(data){
console.log(data.id);
if(!data){
return false;
}
var self = this;
var temp = "";
var infoWindow;
temp = `
<div style="line-height:20px;margin-top:5px;color:#222;font-weight:900;">
<span style="color:#999;">公司名称 :</span>
<span>${data.company}</span>
</div>
<div style="line-height:20px;margin-top:5px;color:#222">
<span style="color:#999">联系人手机 :</span>
<span>${data.mobile}</span>
</div>
<div style="line-height:20px;margin-top:5px;color:#222">
<span style="color:#999">联系人电话 :</span>
<span>${data.tel}</span>
</div>
<div style="line-height:20px;margin-top:5px;color:#f00">
<span style="color:#999">拖车服务 : </span>
<span>${data.trailer_price}元/${data.trailer_k}公里</span>
<span style="margin-left:10px">超过${data.trailer_add}元/公里</span>
</div>
<div style="line-height:20px;margin-top:5px;color:#f00">
<span style="color:#999">路修服务 : </span>
<span>${data.road_price}元/${data.road_k}公里</span>
<span style="margin-left:10px">超过${data.road_add}元/公里</span>
</div>
<div style="line-height:20px;margin-top:5px;color:#f00">
<span style="color:#999">地库拖车 : </span>
<span>${data.basement_trailer}元/次/层</span>
<span style="margin-left:10px">超过${data.basement_trailer_add}元/公里</span>
</div>`;
var info = [];
info.push(temp);
infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(10, -30),
content: info.join("") //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(this.map,[data.lng,data.lat]);
},
//创建服务商点坐标
servicePoint(){
this.map.remove(this.serviceMarker);
this.map.remove(this.serviceMarkerIocn);
this.serviceMarker = [];
this.serviceMarkerIocn = [];
if(this.serviceList.length>0){
this.serviceList.map((data,inx)=>{
if(data.lng&&data.lat){
var html = `<div style='width:100px;text-align:center;font-size:12px;color:#fff;background:rgba(0,0,0,0.8);padding:2px 10px;border-radius:5px;line-height:24px;'>${data.company?data.company:'无'}</div>`;
var serviceMarkerIocn = new AMap.Marker({
position: new AMap.LngLat(data.lng-0,data.lat-0),
icon: service1,
topWhenClick:true,
zIndex:100,
offset: new AMap.Pixel(0, -32)
});
var startMarker = new AMap.Marker({
position: new AMap.LngLat(data.lng-0,data.lat-0),
content: html,
topWhenClick:true,
zIndex:100,
offset: new AMap.Pixel(-50, 0)
});
this.serviceMarkerIocn.push(serviceMarkerIocn);
this.serviceMarker.push(startMarker);
var self = this;
serviceMarkerIocn.on("click",function(e){
self.$emit("rowClick",{
name:"serviceList",
data:data
});
self.serviceInfo(data);
})
serviceMarkerIocn.on("mouseover",function(el){
self.activeMarkSer(inx,data,1);
})
serviceMarkerIocn.on("mouseout",function(el){
self.activeCloseSer(inx,data);
})
}
})
// 将 markers 添加到地图
this.map.add(this.serviceMarker);
this.map.add(this.serviceMarkerIocn);
this.map.setZoomAndCenter(14,this.serviceList.length>0?[this.serviceList[0].lng,this.serviceList[0].lat]:[]);
this.serviceInfo(this.serviceList[0]);//默认显示第一个
}
},
setGps(){
var than = this;
//构造路线导航类
//this.map.clearMap(this.driving);
setTimeout(() => {
if(this.marker){
this.map.remove(this.marker);//清除指定的地图覆盖物
}
if(this.marker1){
this.map.remove(this.marker1);
}
if(this.driving){
this.driving.clear();
}
if(this.list&&this.list[0]&&this.list[0].length>0){
this.marker = new AMap.Marker({
map: this.map,
position: this.list[0],
icon: rescue,
offset: new AMap.Pixel(-26, -52),
autoRotation: true,
//angle:-90,
});
this.map.setZoomAndCenter(11,this.list[0]);
}
if(this.list&&this.list[1]&&this.list[1].length>0){
this.marker1 = new AMap.Marker({
map: this.map,
position: this.list[1],
icon: destination,
offset: new AMap.Pixel(-26, -52),
autoRotation: true,
//angle:-90,
});
this.map.setZoomAndCenter(11,this.list[1]);
//根据起终点经纬度规划驾车导航路线
if(this.list&&this.list[1]&&this.list[1].length>0&&this.list[0]&&this.list[0].length>0){
//显示绿色代表畅通,黄色代表轻微拥堵,红色代表比较拥堵,灰色表示无路况信息
this.driving.search(new AMap.LngLat(this.list[0][0],this.list[0][1]),new AMap.LngLat(this.list[1][0],this.list[1][1]),function(status, result){
than.$emit("setDis",(result.routes[0].distance/1000).toFixed(2));
});
}
}
},0);
}
},
watch:{
motormanList:function(){
if(this.motormanList&&this.motormanList.length>0){
this.point();
}else{
this.map.remove(this.startMarker);
this.map.remove(this.startMarkerIcon);
}
},
serviceList:function(){
if(this.serviceList&&this.serviceList.length>0){
this.servicePoint();
}else{
this.map.remove(this.serviceMarker);
this.map.remove(this.serviceMarkerIocn);
}
},
list:{
handler:function(newVal,oldVal){
this.setGps();
},
deep:true
}
},
mounted(){
this.map = new AMap.Map("container", {
resizeEnable: true,
zoom: 50 //地图显示的缩放级别
});
this.driving = new AMap.Driving({
map: this.map,
panel: "panel",
zoom: 5,
policy: AMap.DrivingPolicy.LEAST_TIME,
hideMarkers:false
});
}
}
</script>
<style scoped lang="scss">
#app,#container{
width: 100%;
height: 100%;
margin: 0 auto;
overflow: hidden;
}
</style>
2.轨迹回放,描点信息窗口
<!----地图组件---画司机轨迹--->
<!---
data 组件数据
---->
<template>
<div id="app">
<div id="container"></div>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import destination from "@/assets/destination.png";
import rescue from "@/assets/rescue.png";
import rise from "@/assets/rise.png";
import red from "@/assets/red.png";
import charector from "@/assets/charector.png";
export default {
props:["list","location","taskList"],
name: 'ymaps',
data(){
var self = this;
return {
map:"",
icon:[rescue,destination],
startMarker:""
}
},
destroyed(){
this.map.destroy();
},
watch:{
list:function(){
this.init();
}
},
methods:{
...mapActions([""]),
//创建点坐标
point(){
console.log(this.location);
// 将 icon 传入 marker
this.map.remove(this.startMarker);
this.startMarker = [];
this.location.map((data,i)=>{
var html = `<div style="width:100px;text-align:center;">
<img src='${this.icon[i]}' width="40" height="48" />
<div style='font-size:12px;color:#fff;background:rgba(0,0,0,0.8);padding:2px 6px;border-radius:5px;line-height:24px;'>${i==0?'救援地':'目的地'}</div>
</div> `;
var startMarker = new AMap.Marker({
position: new AMap.LngLat(data[0]-0,data[1]-0),
content: html,
topWhenClick:true,
zIndex:999999,
offset: new AMap.Pixel(-50, -30)
});
this.startMarker.push(startMarker);
})
if(this.taskList&&this.taskList.length>0){
this.taskList.map((e)=>{
var html = `<div style="width:100px;text-align:center">
<img src='${red}' width="40" height="48" style="margin:0" />
<div style='font-size:12px;color:#fff;background:rgba(0,0,0,0.8);padding:2px 6px;border-radius:5px;line-height:24px;'>${e.statusName}</div>
</div> `;
if(e.location){
var startMarker = new AMap.Marker({
position: new AMap.LngLat(e.location[0]-0,e.location[1]-0),
content: html,
topWhenClick:true,
zIndex:999999,
offset: new AMap.Pixel(-50, -30)
});
this.startMarker.push(startMarker);
}
})
}
this.map.setZoomAndCenter(14,this.location[0]);
// 将 markers 添加到地图
this.map.add(this.startMarker);
},
init(){
var marker;
//测试轨迹数据
// var lineArr = [
// [116.478935,39.997761],
// [116.478939,39.997825],
// [116.478912,39.998549],
// [116.478912,39.998549],
// [116.478998,39.998555],
// [116.478998,39.998555],
// [116.479282,39.998560],
// [116.479658,39.998528],
// [116.480151,39.998453],
// [116.480784,39.998302],
// [116.480784,39.998302],
// [116.481149,39.998184],
// [116.481573,39.997997],
// [116.481863,39.997846],
// [116.482072,39.997718],
// [116.482362,39.997718],
// [116.483633,39.998935],
// [116.483670,39.9989680],
// [116.484648,39.999861]];
this.map = new AMap.Map("container", {
resizeEnable: true,
center: this.list[0],
zoom: 17
});
console.log(this.list);
if(this.list.length>0){
//起点
var marker1 = new AMap.Marker({
map: this.map,
position: this.list[0],
icon: rise,
offset: new AMap.Pixel(-26, -52),
autoRotation: true,
//angle:-90,
});
//小车当前位置
marker = new AMap.Marker({
map: this.map,
position: this.list[this.list.length-1],
icon:charector,
offset: new AMap.Pixel(-26, -13),
autoRotation: true,
angle:-90,
});
}
// 绘制轨迹
var polyline = new AMap.Polyline({
map: this.map,
path: this.list?this.list:[],
showDir:true,
strokeColor: "#28F", //线颜色
// strokeOpacity: 1, //线透明度
strokeWeight: 8, //线宽
// strokeStyle: "solid" //线样式
});
var passedPolyline = new AMap.Polyline({
map: this.map,
//path: lineArr,
strokeColor: "#AF5", //线颜色
// strokeOpacity: 1, //线透明度
strokeWeight: 6, //线宽
// strokeStyle: "solid" //线样式
});
this.point();
}
},
mounted(){
this.init();
}
}
</script>
<style scoped lang="scss">
#app,#container{
width: 100%;
height: 100%;
margin: 0 auto;
overflow: hidden;
}
</style>
3.选取地图位置,搜索地址,拖动地图,始终固定标记位置在地图中间同时解析当前位置信息,显示在下面
<!----地图组件--->
<!---
setSite
---->
<template>
<div id="boxapp">
<div id="containerBox"></div>
<!-- <div id="panel"></div> -->
<div id="myPageTop">
<div class="label">请输入关键字:</div>
<div class="input"><input id="tipinput" placeholder="请输入关键字"/></div>
</div>
<div class="posMsg" v-if="row.location">
<div class="lng flex"><div class="label">经度</div> <div class="value">{{row.location[0]}}</div></div>
<div class="lng flex"><div class="label">纬度</div> <div class="value">{{row.location[1]}}</div></div>
<div class="lng flex">
<div class="label">地址</div>
<div class="value">{{row.name}}</div>
</div>
<div class="lng flex">
<div class="label">详细地址</div>
<div class="value">{{row.address}}</div>
</div>
<div class="btn">
<el-button size="mini" style="width:120px" type="primary" @click="setSite">选择位置</el-button>
<div style="padding-top:10px;">
<el-button size="mini" style="width:120px" @click="cancel">取消</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'mapSite',
data(){
return {
mapBox:"",
row:{},
marker:""
}
},
destroyed(){
//this.map.destroy();
},
methods:{
//取消
cancel(){
this.$emit("cancel",false);
},
//选择位置
setSite(){
this.$emit("setSite",this.row);
},
//标记中心点
rate(center){
var than = this;
if(this.marker){
this.marker.setPosition([center.lng,center.lat]);
}else{
this.marker = new AMap.Marker({
content:"<img style='width:20px;height:30px;' src='//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png'/>",
position: [center.lng,center.lat],
offset: new AMap.Pixel(-10,-30)
});
this.marker.setMap(this.mapBox);
}
AMap.plugin('AMap.Geocoder', function() {
var geocoder = new AMap.Geocoder({
// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
city: '010'
})
var lnglat = [center.lng,center.lat];
geocoder.getAddress(lnglat, function(status, result) {
if (status === 'complete' && result.info === 'OK') {
// result为对应的地理位置详细信息
var pro = result.regeocode.addressComponent;
console.log(result);
than.row = {
address:pro.township+pro.street+pro.streetNumber,
name:pro.province+" "+pro.city+" "+pro.district,
location:lnglat
};
//than.$emit("setSite",than.row);
}
})
})
// this.$emit("setSite",{
// name:e.data.name,
// address:e.data.address?e.data.address:e.data.name,
// location:[e.data.location.lng,e.data.location.lat]
// })
}
},
mounted(){
var than = this;
//地图加载
this.mapBox = new AMap.Map("containerBox", {
resizeEnable: true,
zoom: 12
});
//输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
var placeSearch = new AMap.PlaceSearch({
map: this.mapBox,
//panel:"panel"
}); //构造地点查询类
this.rate(than.mapBox.getCenter());
AMap.event.addListener(auto,"select",function(e){
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); //关键字查询查询
console.log(e.poi);
if(e.poi.location){
than.row = {
name:e.poi.name,
address:Array.isArray(e.poi.address)?e.poi.district:e.poi.address,
location:[e.poi.location.lng,e.poi.location.lat]
}
//than.$emit("setSite",than.row);
}
});//注册监听,当选中某条记录时会触发
AMap.event.addListener(placeSearch,"markerClick", function(e){
than.rate({
lng:e.data.location.lng,
lat:e.data.location.lat
})
than.mapBox.setZoomAndCenter(11,[e.data.location.lng,e.data.location.lat]);
})
this.mapBox.on("click",function(res){
than.rate({
lng:res.lnglat.lng,
lat:res.lnglat.lat
})
than.mapBox.setZoomAndCenter(11,[res.lnglat.lng,res.lnglat.lat]);
})
this.mapBox.on('mapmove', function(){
var center = than.mapBox.getCenter();
than.rate(center);
});
this.mapBox.on('zoomend', function(){
var center = than.mapBox.getCenter();
than.rate(center);
});
}
}
</script>
<style scoped lang="scss">
#boxapp{
width: 100%;
height: 355px;
position: relative;
#containerBox{
width: 100%;
height: 100%;
margin: 0 auto;
overflow: hidden;
background: #f5f5f5;
.search-box{
margin-bottom: 10px;
}
}
.posMsg{
height: 115px;
background: #fff;
overflow: hidden;
border-top:1px solid #ecf5ff;
padding: 10px;
box-sizing: border-box;
left: 0;
font-size: 12px;
position:relative;
.btn{
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
.lng{
line-height: 20px;
color: #999;
span{
color: #0067FF;
}
}
.flex{
display: flex;
.label{
width: 60px;
text-align: right;
padding-right: 10px;
}
.value{
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
width: calc(100% - 200px);
color: #222;
font-size: 12px;
font-weight: 900;
}
}
}
#myPageTop{
position: absolute;
left: 0;
top: 0;
background: #fff;
width: 290px;
padding: 10px;
box-shadow: 0 0 7px 0px rgba(0,0,0,0.5);
.label{
font-size: 12px;
color: #999;
}
.input{
width: 270px;
height: 32px;
line-height: 32px;
margin: 10px 0;
input{
display: block;
width: 100%;
height: 30px;
border: none;
outline: none;
padding: 0 10px;
border-radius: 5px;
border: 1px solid #dcdfe6;
}
input:focus{
border-color: #409EFF;
transition: all 0.5s;
}
}
}
}
</style>
项目测试地址 http://zhongtuoptwebv1.udao.sh.cn
测试账户密码 admin 000000.