官方文档:
https://lbs.amap.com/api/javascript-api-v2/summary
API 文档 :
http://https://lbs.amap.com/api/javascript-api-v2/documentation
个别接口有每日调用限制,如不满足使用需要购买服务包 流量限制说明-地图 JS API 2.0 | 高德地图API*
准备工作:
(注册成为高德开发者进入应用管理,创建新应用,新应用中添加 key,服务平台选择 Web端(JS API))
具体示例:准备-地图 JS API 2.0 | 高德地图API
Web端使用:
安装高德地图加载器插件 : npm i @amap/amap-jsapi-loader -S
代码如下
具体思路:VUE文件created中初始化调用
* 1、初始化加载地图方法
2、如需实时跟踪点位信息需要加上初始化动态刷新坐标的方法(可以采用前端页面轮询或后端Websocket主动发送的方式)(websocket参考上篇文章)
主要方法(初始化加载地图)
AMapLoader.load({
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.InfoWindow', 'AMap.Marker', 'AMap.Polyline', 'AMap.Icon'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
this.map = new AMap.Map("container", { //设置地图容器id
viewMode: "2D", //是否为3D地图模式
zoom: 12, //初始化地图级别
center: [117.125809,36.679151], //初始化地图中心点位置
})
//这里添加需要的地图api、如下图完整代码
}).catch((error) => {
console.log("地图加载失败!",error);
});
},
完整代码
<template>
<div>
<el-row>
<el-col :span="4">
<el-form ref="form" :model="form" label-width="120px">
<el-row>
<el-form-item label="监控类型:">
<el-select v-model="monitor" @change="handleChange" placeholder="选择监控车队" style="width: 150px">
<el-option
v-for="item in monitorOptions"
:key="item.carType"
:label="item.name"
:value="item.carType">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="厂区:">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
<el-checkbox-group v-model="checkedArea" @change="handleCheckedAreas">
<el-checkbox v-for="area in areaOptions" :label="area" :key="area">{{area}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="实时推送:">
<el-button :type="openWs?'danger':'primary'" size="small" @click="openWs?stopWS():openWS()">{{openWs?'关闭':'打开'}}</el-button>
</el-form-item>
</el-row>
</el-form>
</el-col>
<el-col :span="20">
<el-card id="container" class="container-amap">
</el-card>
</el-col>
</el-row>
<el-dialog
title="提示"
:visible.sync="logVisible"
width="500px">
<el-form ref="form" :model="formLog" label-width="80px">
<el-form-item label="日志">
<el-input type="textarea" v-model="formLog.log"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="logVisible = false">取 消</el-button>
<el-button type="primary" @click="logVisible = false">保 存</el-button>
</span>
</el-dialog>
</div>
<!-- <div id="container" class="container-amap">-->
<!-- </div>-->
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader';
import carDirection from '@/assets/images/carDirection.png';
var ws = null;
export default {
name: "M50f01",
data() {
return {
map:null,//地图实例
infoWindow:null,//窗体实例
contextMenuPositon:null,//基点位置
form:{},
formLog:{
log:null
},
factoryArea:0,
checkAll: false,
checkedArea: ["一厂区","二厂区"],
areaOptions: ["一厂区","二厂区"],
isIndeterminate: true,
monitor:"00",//监控车队类型
monitorOptions:[
{
carType:"00",
name:"全部"
},
{
carType:"01",
name:"施工"
},
{
carType:"02",
name:"空车"
},
],
logVisible:false,
marker:null,
markers:[],
openWs:true,
}
},
created() {
//初始化Websocket服务
this.initWebSocket();
//初始化地图服务
this.init();
},
mounted() {
let that = this;
this.$notify({
title: '提示',
message: '车辆【京A·88888】进入施工区域',
duration: 0,
type: 'warning',
position:'bottom-right'
});
}, beforeDestroy() {
// 清除覆盖物/图层
// 清除地图实例上的所有 click 事件绑定
this.map.clearEvents('click');
// 注销地图对象,并清空地图容器
this.map.destroy()
},
methods:{
initWebSocket(){
let that = this;
ws = new WebSocket("ws://IP:端口/ctl/websocket");
// 连接成功后的回调函数
ws.onopen = function (params) {
console.log('客户端连接成功')
// 向服务器发送消息
ws.send('认证成功!')
};
// 从服务器接受到信息时的回调函数
ws.onmessage = function (e) {
console.log('收到服务器响应', e.data)
this.proTriaxialData = e.data;
console.log( this.proTriaxialData);
var data = e.data;
if(data!=undefined){
if(data.indexOf("{") != -1){
var obj = JSON.parse(data);
if(obj.hasOwnProperty("lng")){
console.info(obj);
var point = new AMap.LngLat(obj.lng,obj.lat);
that.addMarker2(point,obj);
}
}else{
console.log(data);
}
}
};
// 连接关闭后的回调函数
ws.onclose = function(evt) {
console.log("关闭客户端连接");
};
// 连接失败后的回调函数
ws.onerror = function (evt) {
console.log("连接失败了",evt);
};
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,这样服务端会抛异常。
window.onbeforeunload = function() {
ws.close();
}
console.log(ws)
},
//打开推送
openWS(){
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
this.initWebSocket();
this.openWs = true;
} else {
this.openWs = false;
alert('当前浏览器 Not support websocket')
}
},
//关闭推送
stopWS(){
console.log("close");
ws.close();
this.openWs = false;
},
init() { //调用路径规划插件需要添加安全密钥
window._AMapSecurityConfig = {
securityJsCode: "xxxxxxxxxxxxxxxxxxxxxxxx",
}
AMapLoader.load({
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.InfoWindow', 'AMap.Marker', 'AMap.Polyline', 'AMap.Icon','AMap.Geolocation', 'AMap.Driving'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
this.map = new AMap.Map("container", { //设置地图容器id
viewMode: "2D", //是否为3D地图模式
zoom: 12, //初始化地图级别
center: [117.125809,36.679151], //初始化地图中心点位置
})
this.map.on('click', (e) => console.log(e));
this.addTools();//添加工具栏
this.addMarker() // 添加标记点
// this.onabort() // 配置路线
// this.infoWindowOpt() // 置弹窗
this.addCircle(); // 添加圆形区域
this.addPolygon(); //添加多边形区域
this.addRightMenu(); this.searchDriving();//路径规划
// this.setData(this.vehicleGis || [], this.planGis || []) // 传入后台初始化数据
}).catch((error) => {
console.log("地图加载失败!",error);
});
}, searchDriving(){
let that = this
let driving = new AMap.Driving({
map: that.map,
panel: 'panel',
policy:18
})
driving.search(
new AMap.LngLat(117.202322,36.693391),
new AMap.LngLat(117.120134,36.657355),
function (status, result) {
// result 即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
if (status === 'complete') {
console.log('绘制驾车路线完成', result)
} else {
console.log('获取驾车数据失败:' + result)
}
}
)
},
addTools(){
let that = this;
AMap.plugin(
[
"AMap.ToolBar",
"AMap.Scale",
"AMap.HawkEye",
"AMap.MapType",
"AMap.Geolocation",
"AMap.ControlBar",
],
function () {
//添加工具条控件,工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
// that.map.addControl(new AMap.ToolBar());
//添加比例尺控件,展示地图在当前层级和纬度下的比例尺
that.map.addControl(new AMap.Scale());
//添加鹰眼控件,在地图右下角显示地图的缩略图
// that.map.addControl(new AMap.HawkEye({ isOpen: true }));
//添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
that.map.addControl(new AMap.MapType());
//添加定位控件,用来获取和展示用户主机所在的经纬度位置
// that.map.addControl(new AMap.Geolocation());
//添加控制罗盘控件,用来控制地图的旋转和倾斜
that.map.addControl(new AMap.ControlBar());
}
);
},
//添加右键菜单
addRightMenu(){
let that = this;
//创建右键菜单
var contextMenu = new AMap.ContextMenu();
//右键放大
contextMenu.addItem("放大一级", function () {
that.map.zoomIn();
}, 0);
//右键缩小
contextMenu.addItem("缩小一级", function () {
that.map.zoomOut();
}, 1);
//右键显示全国范围
contextMenu.addItem("缩放至全国范围", function (e) {
that.map.setZoomAndCenter(4, [108.946609, 34.262324]);
}, 2);
//右键显示初始化视图
contextMenu.addItem("返回初始化视图", function (e) {
that.map.setZoomAndCenter(12, [117.125809,36.679151]);
}, 3);
//右键添加Marker标记
contextMenu.addItem("添加标记", function (e) {
var marker = new AMap.Marker({
map: that.map,
position: that.contextMenuPositon //基点位置
});
marker.on('click', ({ lnglat }) => {
console.log("删除此标记");
that.map.remove(marker);
})
}, 4);
//右键记录日志
contextMenu.addItem("记录日志", function (e) {
console.log("记录日志",that.contextMenuPositon);
that.logVisible = true;
}, 5);
//地图绑定鼠标右击事件——弹出右键菜单
that.map.on('rightclick', function (e) {
contextMenu.open(that.map, e.lnglat);
that.contextMenuPositon = e.lnglat;
});
contextMenu.open(that.map, that.contextMenuPositon);
},
//添加多边形区域
addPolygon(){
const area1 = [
[117.042754, 36.666346],
[117.044042,36.6892],
[117.063568,36.701209],
[117.072913,36.685365],
[117.073396,36.666346],
];
const area2 = [
[117.056176,36.679066],
[117.056202,36.674876],
[117.057179,36.674231],
[117.057168,36.67198],
[117.061599,36.672006],
[117.061599,36.672596],
[117.064104,36.672583],
[117.063868,36.679725],
[117.056229,36.679045]
];
const pathArr = [area1,area2];
const polygon = new AMap.Polygon({
path: pathArr, //多边形路径
fillColor: "#ccebc5", //多边形填充颜色
strokeOpacity: 1, //线条透明度
fillOpacity: 0.5, //填充透明度
strokeColor: "#2b8cbe", //线条颜色
strokeWeight: 1, //线条宽度
strokeStyle: "dashed", //线样式
strokeDasharray: [5, 5], //轮廓的虚线和间隙的样式
extData:{
areaType:"一厂区"
}
});
//鼠标移入更改样式
polygon.on("mouseover", () => {
polygon.setOptions({
fillOpacity: 0.7, //多边形填充透明度
fillColor: "#7bccc4",
});
});
//鼠标移出恢复样式
polygon.on("mouseout", () => {
polygon.setOptions({
fillOpacity: 0.5,
fillColor: "#ccebc5",
});
});
this.map.add(polygon);
var inRing = AMap.GeometryUtil.isPointInRing([117.056376,36.68915], area1);
var inRing2 = AMap.GeometryUtil.isPointInRing([117.034189,36.685812], area1);
var inRing3 = AMap.GeometryUtil.isPointInRing([117.06096,36.676369], area1);
console.log("inRing",inRing);
console.log("inRing2",inRing2);
console.log("inRing3",inRing3);
},
//添加圆形区域
addCircle(){
let that = this;
//设置圆形位置
var center = new AMap.LngLat(117.185774,36.680654);
//设置圆的半径大小
var radius = 1000;
//创建圆形 Circle 实例
var circle = new AMap.Circle({
center: center, //圆心
radius: radius, //半径
borderWeight: 1, //描边的宽度
strokeColor: "#FF33FF", //轮廓线颜色
strokeOpacity: 1, //轮廓线透明度
strokeWeight: 1, //轮廓线宽度
fillOpacity: 0.4, //圆形填充透明度
strokeStyle: "dashed", //轮廓线样式
strokeDasharray: [10, 10],
fillColor: "#1791fc", //圆形填充颜色
zIndex: 50, //圆形的叠加顺序
extData:{
areaType:"二厂区"
}
});
//圆形 Circle 对象添加到 Map
this.map.add(circle);
//根据覆盖物范围调整视野
// this.map.setFitView([ circle ]);
//鼠标移入事件
// circle.on("mouseover", function () {
// console.log("鼠标移入,添加窗体");
// var content = [
// "<div><b>高德软件有限公司</b>",
// "电话 : 010-84107000 邮编 : 100102",
// "地址 : 北京市望京阜通东大街方恒国际中心A座16层</div>",
// ];
// that.addInfoModel(content);
// });
// circle.on("mouseout", function () {
// console.log("鼠标移出,关闭窗体");
// that.infoWindow.close();
// });
},
// 添加起始点和车子
addMarker() {
// var marker1 = new AMap.Marker({
// map: this.map,
// position: [117.185774,36.680654],
// clickable: true,//是否可以点击
// angle:180,//设置标记点的旋转角度
// icon: require('@/assets/images/carDirection.png'),
// anchor: 'bottom-center',
// extData:{
// id:1,
// deptId:263,
// carType:"01"
// }
// })
// console.log("this.marker1",marker1);
//
// //模拟车辆动态移动
// let lnt = 36.680654;
// let angle = 90;
// // 设置定时器,每隔5秒执行一次
// var timerMarker11 = setInterval(function() {
// // 在这里写需要执行的代码
// lnt = lnt + 0.001;
// marker1.setPosition([117.185774,lnt]);
// if(lnt>=36.720000){
// lnt = 36.680654;
// }
// // angle = angle - 30;
// // if(angle==-360){
// // angle = 0;
// // }
// // marker1.setAngle(angle);
// // console.log("实时位置",marker1.getPosition());
// }, 1000);
var marker2 = new AMap.Marker({
map: this.map,
zIndex: 12,
position: [117.130358,36.6854],
angle:45,//设置标记点的旋转角度
// topWhenClick: false,
icon: require('@/assets/images/carDirection.png'),
anchor: 'middle-left',
extData:{
id:2,
deptId:263,
carType:"01"
}
});
var marker3 = new AMap.Marker({
map: this.map,
position: [117.064781,36.681457],
// clickable: false,
angle:0,//设置标记点的旋转角度
icon: require('@/assets/images/carDirectionNull.png'),
anchor: 'bottom-center',
extData:{
id:3,
deptId:263,
carType:"02"
}
});
// marker1.on('click', ({ lnglat }) => {
// console.log("点击事件",marker1.getExtData());
// var content = [
// "<div><b>车辆信息</b>",
// "车牌号【鲁A·88888】",
// "车主 : 张三 手机号 : 18888888888",
// "状态 : 运输中</div>",
// ];
// this.addInfoModel(content, [lnglat.lng, lnglat.lat]);
// })
marker2.on('click', ({ lnglat }) => {
console.log("点击事件",lnglat);
var content = [
"<div><b>车辆信息</b>",
"车主 : 李四 手机号 : 18888888888",
"状态 : 运输中</div>",
];
this.addInfoModel(content, [lnglat.lng, lnglat.lat]);
})
marker3.on('click', ({ lnglat }) => {
console.log("点击事件",lnglat);
var content = [
"<div><b>车辆信息</b>",
"车主 : 王五 手机号 : 18888888888",
"状态 : 运输中</div>",
];
this.addInfoModel(content, [lnglat.lng, lnglat.lat]);
})
},
// 添加动态点
addMarker2(point,obj){
//路口名称
var addrName = obj.carNumber;
//人流量
var weight = obj.weight;
//信息窗口
// var contents = '<div style="width: 200px;border: solid 1px silver;">' +
// '<div style="position: relative;background: none repeat scroll 0 0 #F9F9F9;border-bottom: 1px solid #CCC;border-radius: 5px 5px 0 0;"></div>' +
// '<div style="font-size: 14px;padding: 6px;line-height: 20px;background-color: white;height:67px;"><strong>车辆:</strong>:'+addrName+'<br><strong>运载重量:</strong>:'+weight+' 吨</div>' +
// '<div style="height: 0px;width: 100%;clear: both;text-align: center;position: relative; top: 0px; margin: 0px auto;"><img style="transform: rotate(-180deg);" src="'+ carDirection + '"></div>' +
// '</div>';
//点标记对象
var marker = new AMap.Marker({
// content:contents,
position: point,
angle:180,//设置标记点的旋转角度
icon: require('@/assets/images/carDirectionNull.png'),
extData:{addrName:addrName},
// offset: new AMap.Pixel(-13, -30)
});
marker.on('click', ({ lnglat }) => {
var content = [
"<div><b>车辆信息</b>",
"车牌号【京A·88888】",
"车主 : 张三 手机号 : 18888888888",
"状态 : 运输中</div>",
];
this.addInfoModel(content, [lnglat.lng, lnglat.lat]);
})
//优先判断是否为空对象
if(this.markers.length>0){
//根据路口名称查询存在的索引 不存在返回-1
var index = this.isExist(addrName);
if(index>=0){
//先清空之前的对象
this.markers[index].setMap(null);
//再把最新的点渲染到地图
marker.setMap(this.map);
//更新最新的点到markers数组
this.markers[index] = marker;
// this.map.setFitView();
}else{
marker.setMap(this.map);
this.markers.push(marker)
// this.map.setFitView();
}
} else {
marker.setMap(this.map);
this.markers.push(marker)
// this.map.setFitView();
}
},
isExist(addrName) {
var index = -1;
for (var i = 0; i < this.markers.length; i++) {
var element = this.markers[i]
console.log(" element.getExtData().", element.getExtData())
var dataAddrName = element.getExtData().addrName;
if(dataAddrName==addrName){
index = i;
}else{
continue;
}
}
return index;
},
// 添加多个途径点
addMarkerCon() {
this.data.waypoints.forEach((m, i) => {
if (i !== this.data.waypoints.length - 1) {
const { clientLongitude, clientLatitude, clientName, clientAddr } = m
var marker = new AMap.Marker({
map: this.map,
position: [clientLongitude, clientLatitude],
icon: require('@/assets/images/carDirection.png'),
// anchor: 'middle-left',
offset: new AMap.Pixel(-13, -30),
});
marker.on('click', ({ lnglat }) => this.markerClick(lnglat, clientName, clientAddr));
// marker.emit('click', { target: marker });//默认初始化不出现信息窗体,打开初始化就出现信息窗体
this.markers.push(marker);
}
});
},
// 途径点和终点的信息窗体
markerClick({ lng, lat }, name, ads) {
const con = `<div><div style="font-size: 14px;font-weight: bold;color: #333;">${name || ""}</div><span style="font-size: 12px;color: #999;">${ads || ''}</span></div>`
this.infoWindowZ.setContent(con);
this.infoWindowZ.open(this.map, [lng, lat]);
// this.infoWindowZ.open(this.map, [lnglat.lng, lnglat.lat]);
},
infoWindowOpt() {
const content = ``
this.infoWindow = new AMap.InfoWindow({
isCustom: true, //使用自定义窗体
closeWhenClickMap: true,//控制是否在鼠标点击地图后关闭信息窗体
anchor: 'middle-left',
content,
offset: new AMap.Pixel(42, -25),
});
this.infoWindowZ = new AMap.InfoWindow({
closeWhenClickMap: true,
content: '',
offset: new AMap.Pixel(0, -16),
});
// this.infoWindow.close(); // 关闭窗体
},
/**
* 参数:
* fromPoint: [经度,纬度] ------ 起点
* toPoint :[经度,纬度] ------ 终点
*
* 返回值:
* 0-360的角度值
**/
getAngle(fromPoint, toPoint) {
// 获取两点弧度
var radian = Math.atan2(toPoint[1] - fromPoint[1], toPoint[0] - fromPoint[0]);
// 转成角度
var angle = radian * 180 / Math.PI;
// 确保角度在0—360之间
//将负值转化为正值
if (angle < 0) angle += 360;
//将0-180的y为负的转化为180-360之间
if (toPoint[1] < fromPoint[1]) angle += 180;
//调整角度为arcgis的角度,即setAngle(角度)
if (angle >= 0 && angle <= 180) angle = 180 - angle;
else if (angle > 180 && angle <= 360) angle = 540 - angle;
else if (angle > 360) angle = angle % 360;
return Number(angle);
},
//添加信息窗体 (内容,坐标)
addInfoModel(content,coordinate){
//创建 infoWindow 实例
var infoWindow = new AMap.InfoWindow({
content: content.join("<br>"), //传入字符串拼接的 DOM 元素
anchor: "top-left",
});
// console.log(this.map.getCenter());
//打开信息窗体
infoWindow.open(this.map, coordinate); //map 为当前地图的实例,map.getCenter() 用于获取地图中心点坐标。
},
//选择监控类型的车辆
handleChange(carType){
let that = this;
console.log("carType",carType);
// 获取所有的 Marker
let allOverlays = this.map.getAllOverlays('marker');
console.log("allOverlays",allOverlays); // 打印所有 Marker
if(allOverlays.length>0){
allOverlays.forEach(e=>{
if(carType === '00'){
e.show();
}else{
if(that.checkEmpty(e.getExtData())||e.getExtData().carType !== carType){
e.hide();
}else{
e.show();
}
}
})
// 更新视图
// that.map.setFitView();
}
},
handleCheckedAreas(value){
console.log("value",value)
let checkedCount = value.length;
this.checkAll = checkedCount === this.areaOptions.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < this.areaOptions.length;
this.handleClcAreaIsShow();
},
handleCheckAllChange(val){
console.log("val",val)
this.checkedArea = val ? this.areaOptions : [];
this.isIndeterminate = false;
this.handleClcAreaIsShow();
},
handleClcAreaIsShow(){
let that = this;
let allOverlays = that.getAllPolygonsAndCircles();
if(allOverlays.length>0){
allOverlays.forEach(e=>{
if(!that.checkEmpty(e.getExtData())){
if(that.checkedArea.length>0){
// console.log("e.getExtData().areaType",e.getExtData().areaType);
if(that.checkedArea.includes(e.getExtData().areaType)){
e.show();
}else{
e.hide();
}
}else{
e.hide();
}
}
})
}
},
// 函数:获取所有多边形和圆形区域
getAllPolygonsAndCircles() {
var allOverlays = this.map.getAllOverlays('polygon'); // 获取所有的多边形
allOverlays = allOverlays.concat(this.map.getAllOverlays('circle')); // 合并圆形
return allOverlays;
},
checkEmpty(e){
if(e==null||typeof (e) =='undefined'||e===""){
return true;
}
return false;
},
}
}
</script>
<style scoped>
.container-amap{
width: 100%;
height: 850px;
}
</style>