Prerequisite: You need to register for the Amap open platform, then create an application and activate
Web端(JS API)
the platform, and then getsecurityJsCode
thekey
1. Basic extraction (restore example)
1.1 Component code
Code description:
- Need to modify
securityJsCode
andkey
make your ownallowCollision
Whether to avoid markers for labeling, the default is false and does not avoid markers.markers
an array of markers on the maplayer
is an annotation layer, which can be understood as a layer- The process is actually just
markers
loading tolayer
and thenlayer
loading to map.this.map.setFitView(null, false, [100, 150, 10,10]);
- According to the distribution of the coverage added on the map, the map is automatically zoomed to the appropriate field of view level, and the parameters can be defaulted.
overlayList
It is an array of overlays. By default, it is all overlay layers added to the current map. Itimmediately
represents whether the animation process is required.avoid
It represents the pixel avoidance width of the top, bottom, left and right, andmaxZoom
represents the maximum level after fitView.- Parameter Description:
setFitView(overlays, immediately, avoid, maxZoom)
- overlays
(Array<Overlay>)
covering- immediately
(Boolean = false)
whether to transition immediately- Avoid
(Array<Number> = [60,60,60,60])
the surrounding distance, up, down, left, right- maxZoomMaximum
(Number = zooms[1])
zoom levelallowCollisionFunc
notAllowCollisionFunc
I have not used the and method. Its main function is to control the labeling and avoid markers.
- If you need this function to create two new buttons, just click the event to bind these two methods;
toggleBtn
The method is to modify whether the control label avoidance button is used (disable)
- If you need vue to implement this function, you only need to bind the corresponding button's disable to
allowCollision
;
<template>
<div id="container"></div>
</template>
<script>
//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
//例如: import 《组件名称》 from '《组件路径》 ';
import AMapLoader from "@amap/amap-jsapi-loader";
import moment from "moment";
import {getTrackList} from '@/services/attendance/statistics.js'
// 设置安全密钥
window._AMapSecurityConfig = {
securityJsCode: 'xxxx你的securityJsCodexxxx',
}
export default {
name: 'PositionContainer',
//import 引入的组件需要注入到对象中才能使用
components: {},
props: {
},
data() {
//这里存放数据
return {
AMap: null,
//此处不声明 map 对象,可以直接使用 this.map赋值或者采用非响应式的普通对象来存储。
map: null,
mouseTool: null,
marker: null,
allowCollision: false,//标注避让marker
markers: [],
layer: null,
};
},
//计算属性 类似于 data 概念
computed: {},
//监控 data 中的数据变化
watch: {
},
//方法集合
methods: {
allowCollisionFunc () {
this.allowCollision = true;
this.layer.setAllowCollision(true);
this.toggleBtn();
},
notAllowCollisionFunc () {
this.allowCollision = false;
this.layer.setAllowCollision(false);
this.toggleBtn();
},
toggleBtn (){
var allowCollisionBtn = document.getElementById('allowCollision');
var notAllowCollisionBtn = document.getElementById('notAllowCollision');
var disableClass = 'disable';
if(this.allowCollision){
allowCollisionBtn.classList.add(disableClass);
notAllowCollisionBtn.classList.remove(disableClass);
}else {
allowCollisionBtn.classList.remove(disableClass);
notAllowCollisionBtn.classList.add(disableClass);
}
},
initMarkers(AMap) {
// 设置一个图标对象
var icon = {
// 图标类型,现阶段只支持 image 类型
type: 'image',
// 图片 url
image: 'https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png',
// 图片尺寸
size: [64, 30],
// 图片相对 position 的锚点,默认为 bottom-center
anchor: 'center',
};
var textStyle = {
fontSize: 12,
fontWeight: 'normal',
fillColor: '#22886f',
strokeColor: '#fff',
strokeWidth: 2,
fold: true,
padding: '2, 5',
};
var LabelsData = [
{
name: '自提点1',
position: [116.461009, 39.991443],
zooms: [10, 20],
opacity: 1,
zIndex: 10,
fold: true,
icon,
text: {
// 要展示的文字内容
content: '中邮速递易',
// 文字方向,有 icon 时为围绕文字的方向,没有 icon 时,则为相对 position 的位置
direction: 'right',
// 在 direction 基础上的偏移量
offset: [-20, -5],
// 文字样式
style: {
// 字体大小
fontSize: 12,
// 字体颜色
fillColor: '#22886f',
//
strokeColor: '#fff',
strokeWidth: 2,
fold: true,
padding: '2, 5',
}
}
},
{
name: '自提点2',
position: [116.466994, 39.984904],
zooms: [10, 20],
opacity: 1,
zIndex: 16,
icon,
text: {
content: '丰巢快递柜-花家地北里',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点3',
position: [116.472914, 39.987093],
zooms: [10, 20],
opacity: 1,
zIndex: 8,
icon,
text: {
content: '丰巢快递柜-中环南路11号院',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点4',
position: [116.471814, 39.995856],
zooms: [10, 20],
opacity: 1,
zIndex: 23,
icon,
text: {
content: '丰巢快递柜-合生麒麟社',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点5',
position: [116.469639, 39.986889],
zooms: [10, 20],
opacity: 1,
zIndex: 6,
icon,
text: {
content: '速递易快递柜-望京大厦',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点6',
position: [116.467361, 39.996361],
zooms: [10, 20],
opacity: 1,
zIndex: 5,
icon,
text: {
content: 'E栈快递柜-夏都家园',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点7',
position: [116.462327, 39.996071],
zooms: [10, 20],
opacity: 1,
zIndex: 4,
icon,
text: {
content: '丰巢自提柜-圣馨大地家园',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点8',
position: [116.462349, 39.996067],
zooms: [10, 20],
opacity: 1,
zIndex: 3,
icon,
text: {
content: '丰巢快递-圣馨大地家园',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
},
{
name: '自提点9',
position: [116.456474, 39.991563],
zooms: [10, 20],
zIndex: 2,
opacity: 1,
icon,
text: {
content: 'E栈快递柜-南湖渠西里',
direction: 'right',
offset: [-20, -5],
style: textStyle
}
}
];
this.layer = new AMap.LabelsLayer({
zooms: [3, 20],
zIndex: 1000,
// collision: false,
// 设置 allowCollision:true,可以让标注避让用户的标注
allowCollision: this.allowCollision,
});
this.layer.add(this.markers);
// 图层添加到地图
this.map.add(this.layer);
// 初始化 labelMarker
for (var i = 0; i < LabelsData.length; i++) {
var curData = LabelsData[i];
curData.extData = {
index: i
};
var labelMarker = new AMap.LabelMarker(curData);
this.markers.push(labelMarker);
}
// 将 marker 添加到图层
this.layer.add(this.markers);
this.map.setFitView(null, false, [100, 150, 10, 10]);
this.toggleBtn()
},
initMap() {
AMapLoader.load({
key: "xxxx你的keyCodexxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
"plugins": [
"AMap.Scale",
"AMap.HawkEye",
"AMap.ToolBar",
"AMap.AutoComplete",
"AMap.PlaceSearch",
"AMap.ControlBar",
"AMap.MouseTool",
"AMap.DragRoute",
"AMap.MoveAnimation"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
this.AMap=AMap
this.map = new AMap.Map("container", { //设置地图容器id
zoom: 15.8, // 初始化地图级别
center: [116.469881, 39.993599], //中心点坐标 成都 104.065735, 30.659462
showIndoorMap: false,
});
this.initMarkers(AMap);
}).catch(e => {
console.log(e);
})
},
},
//生命周期 - 创建完成(可以访问当前 this 实例)
created() {
// this.getLineArr(this.equipmentId,moment().valueOf())
},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() {
this.initMap();
},
//生命周期 - 创建之前
beforeCreate() {
},
//生命周期 - 挂载之前
beforeMount() {
},
//生命周期 - 更新之前
beforeUpdate() {
},
//生命周期 - 更新之后
updated() {
},
//生命周期 - 销毁之前
beforeDestroy() {
},
//生命周期 - 销毁完成
destroyed() {
},
//如果页面有 keep-alive 缓存功能, 这个函数会触发
activated() {
},
}
</script>
<style scoped>
#container {
padding: 0px;
margin: 0px;
width: 100%;
height: 800px;
}
.input-item {
height: 2.2rem;
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-radius: .25rem;
width: 10rem;
border-width: 0;
border-radius: 0.4rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
position: fixed;
bottom: 12rem;
right: 2rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
}
</style>
1.2 Usage examples
Just introduce components
<template>
<PositionContainer></PositionContainer>
</template>
<script>
//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
//例如: import 《组件名称》 from '《组件路径》 ';
import PositionContainer from '@/pages/components/map/PositionContainer';
export default {
name: 'Position',
//import 引入的组件需要注入到对象中才能使用
components: {PositionContainer},
props: {},
data() {
//这里存放数据
return {};
},
//计算属性 类似于 data 概念
computed: {},
//监控 data 中的数据变化
watch: {},
//方法集合
methods: {},
//生命周期 - 创建完成(可以访问当前 this 实例)
created() {},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() {},
//生命周期 - 创建之前
beforeCreate() {},
//生命周期 - 挂载之前
beforeMount() {},
//生命周期 - 更新之前
beforeUpdate() {},
//生命周期 - 更新之后
updated() {},
//生命周期 - 销毁之前
beforeDestroy() {},
//生命周期 - 销毁完成
destroyed() {},
//如果页面有 keep-alive 缓存功能, 这个函数会触发
activated() {},
}
</script>
<style scoped>
</style>
1.3 Achieve results
2. Advanced extraction (customized points + different icons for each point + different labels for each point)
The point data here is the data returned by the backend. If necessary, you can simulate the data yourself.
The data structure returned by the backend is similar to the following
[ { "sys_time": 1674206183000, "user_name": "名称1", "jingdu": 104.751846, "weidu": 31.767537, "sendTime": "2023-01-20 17:16:23" }, { "sys_time": 1677735439000, "user_name": "名称2", "jingdu": 104.7560758, "weidu": 31.767168, "sendTime": "2023-01-20 17:16:23" } ]
2.1 Component code
Code description:
getNewestPositions
The method is to call the backend interface to return data- Then assemble the back-end list traversal into the array we need
LabelsData
content: item.user_name+'-'+item.sendTime
Set up our display label,image: 'https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png',
Set the icon of our point. After subsequent users have the icon, they can get data from the backend. I will write it down first.- Set the first data of the backend data to the center of the map
<template>
<div id="container"></div>
</template>
<script>
//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
//例如: import 《组件名称》 from '《组件路径》 ';
import AMapLoader from "@amap/amap-jsapi-loader";
import {getNewestPositions} from '@/services/attendance/position.js'
// 设置安全密钥
window._AMapSecurityConfig = {
securityJsCode: 'xxxx你的securityJsCodexxxx',
}
export default {
name: 'PositionContainer',
//import 引入的组件需要注入到对象中才能使用
components: {},
props: {
},
data() {
//这里存放数据
return {
AMap: null,
//此处不声明 map 对象,可以直接使用 this.map赋值或者采用非响应式的普通对象来存储。
map: null,
mouseTool: null,
marker: null,
allowCollision: false,//标注避让marker
markers: [],
layer: null,
LabelsData:[],
center: [104.065735, 30.659462],
};
},
//计算属性 类似于 data 概念
computed: {},
//监控 data 中的数据变化
watch: {
},
//方法集合
methods: {
newestPositions () {
getNewestPositions().then(res => {
if (res.data.code==0){
var postions = res.data.data
console.log(res.data.data)
this.LabelsData =res.data.data.map(item=>{
var labelsData = {
name: item.user_name,
position: [item.jingdu, item.weidu],
zooms: [10, 20],
opacity: 1,
zIndex: 10,
fold: true,
icon: {
// 图标类型,现阶段只支持 image 类型
type: 'image',
// 图片 url
image: 'https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png',
// 图片尺寸
size: [64, 30],
// 图片相对 position 的锚点,默认为 bottom-center
anchor: 'center',
},
text: {
// 要展示的文字内容
content: item.user_name+'-'+item.sendTime,
// 文字方向,有 icon 时为围绕文字的方向,没有 icon 时,则为相对 position 的位置
direction: 'right',
// 在 direction 基础上的偏移量
offset: [-20, -5],
// 文字样式
style: {
// 字体大小
fontSize: 12,
// 字体颜色
fillColor: '#22886f',
//
strokeColor: '#fff',
strokeWidth: 2,
fold: false,
padding: '2, 5',
}
}
}
return labelsData
})
this.center=[postions[0].jingdu, postions[0].weidu]
this.initMap()
}else {
this.$message.error(res.data.msg)
}
})
},
initMarkers(AMap) {
this.layer = new AMap.LabelsLayer({
zooms: [3, 20],
zIndex: 1000,
// collision: false,
// 设置 allowCollision:true,可以让标注避让用户的标注
allowCollision: this.allowCollision,
});
this.layer.add(this.markers);
// 图层添加到地图
this.map.add(this.layer);
// 初始化 labelMarker
for (var i = 0; i < this.LabelsData.length; i++) {
var curData = this.LabelsData[i];
curData.extData = {
index: i
};
var labelMarker = new AMap.LabelMarker(curData);
this.markers.push(labelMarker);
}
// 将 marker 添加到图层
this.layer.add(this.markers);
this.map.setFitView(null, false, [100, 150, 10, 10]);
// this.toggleBtn()
},
initMap() {
AMapLoader.load({
key: "xxxx你的keyxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
"plugins": [
"AMap.Scale",
"AMap.HawkEye",
"AMap.ToolBar",
"AMap.AutoComplete",
"AMap.PlaceSearch",
"AMap.ControlBar",
"AMap.MouseTool",
"AMap.DragRoute",
"AMap.MoveAnimation"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
this.AMap=AMap
this.map = new AMap.Map("container", { //设置地图容器id
zoom: 15.8, // 初始化地图级别
center: this.center, //中心点坐标 成都 104.065735, 30.659462
showIndoorMap: false,
});
this.initMarkers(AMap);
}).catch(e => {
console.log(e);
})
},
},
//生命周期 - 创建完成(可以访问当前 this 实例)
created() {
this.newestPositions()
},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() {
this.initMap();
},
//生命周期 - 创建之前
beforeCreate() {
},
//生命周期 - 挂载之前
beforeMount() {
},
//生命周期 - 更新之前
beforeUpdate() {
},
//生命周期 - 更新之后
updated() {
},
//生命周期 - 销毁之前
beforeDestroy() {
},
//生命周期 - 销毁完成
destroyed() {
},
//如果页面有 keep-alive 缓存功能, 这个函数会触发
activated() {
},
}
</script>
<style scoped>
#container {
padding: 0px;
margin: 0px;
width: 100%;
height: 800px;
}
.input-item {
height: 2.2rem;
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-radius: .25rem;
width: 10rem;
border-width: 0;
border-radius: 0.4rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
position: fixed;
bottom: 12rem;
right: 2rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
}
</style>
2.2 Usage examples
Refer to 1.2, no changes
2.3 Extraction effect
After zooming in on the map
3. Final extraction (regular refresh points)
3.1 Component code
Code description:
- Use timers to do scheduled tasks
this.timer = setInterval(this.newestPositionsWithoutInitMap, 120 * 1000);
- Remember
beforeDestroy()
whenclearInterval(this.timer);
this.map.setFitView(null, false, [100, 150, 10, 10]);
Zoom the map to the appropriate location
- This will cause the map to be zoomed to the maximum every time we refresh it, because of this
- The core idea is to regularly request the backend interface through a timer, and then render the map markers.
<template>
<div id="container"></div>
</template>
<script>
//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
//例如: import 《组件名称》 from '《组件路径》 ';
import AMapLoader from "@amap/amap-jsapi-loader";
import {getNewestPositions} from '@/services/attendance/position.js'
// 设置安全密钥
window._AMapSecurityConfig = {
securityJsCode: 'xxxx你的securityJsCodexxxx',
}
export default {
name: 'PositionContainer',
//import 引入的组件需要注入到对象中才能使用
components: {},
props: {
},
data() {
//这里存放数据
return {
AMap: null,
//此处不声明 map 对象,可以直接使用 this.map赋值或者采用非响应式的普通对象来存储。
map: null,
mouseTool: null,
marker: null,
allowCollision: false,//标注避让marker
markers: [],
layer: null,
LabelsData:[],
center: [104.065735, 30.659462],
timer: '',
zoom: '',
};
},
//计算属性 类似于 data 概念
computed: {},
//监控 data 中的数据变化
watch: {
},
//方法集合
methods: {
createLable: function (res) {
var postions = res.data.data
this.LabelsData = res.data.data.map(item => {
var labelsData = {
name: item.user_name,
position: [item.jingdu, item.weidu],
zooms: [10, 20],
opacity: 1,
zIndex: 10,
fold: true,
icon: {
// 图标类型,现阶段只支持 image 类型
type: 'image',
// 图片 url
image: 'https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png',
// 图片尺寸
size: [64, 30],
// 图片相对 position 的锚点,默认为 bottom-center
anchor: 'center',
},
text: {
// 要展示的文字内容
content: item.user_name + '-' + item.sendTime,
// 文字方向,有 icon 时为围绕文字的方向,没有 icon 时,则为相对 position 的位置
direction: 'right',
// 在 direction 基础上的偏移量
offset: [-20, -5],
// 文字样式
style: {
// 字体大小
fontSize: 12,
// 字体颜色
fillColor: '#22886f',
//
strokeColor: '#fff',
strokeWidth: 2,
fold: false,
padding: '2, 5',
}
}
}
return labelsData
})
this.center = [postions[0].jingdu, postions[0].weidu]
},
newestPositions () {
getNewestPositions().then(res => {
if (res.data.code==0){
this.createLable(res);
this.initMap()
}else {
this.$message.error(res.data.msg)
}
})
},
newestPositionsWithoutInitMap () {
getNewestPositions().then(res => {
if (res.data.code==0){
this.createLable(res);
this.initMarkers(this.AMap)
}else {
this.$message.error(res.data.msg)
}
})
},
initMarkers(AMap) {
this.markers=[]
this.layer = new AMap.LabelsLayer({
zooms: [3, 20],
zIndex: 1000,
// collision: false,
// 设置 allowCollision:true,可以让标注避让用户的标注
allowCollision: this.allowCollision,
});
this.layer.add(this.markers);
// 图层添加到地图
this.map.clearMap()
this.map.add(this.layer);
// 初始化 labelMarker
for (var i = 0; i < this.LabelsData.length; i++) {
var curData = this.LabelsData[i];
curData.extData = {
index: i
};
var labelMarker = new AMap.LabelMarker(curData);
this.markers.push(labelMarker);
}
// 将 marker 添加到图层
this.layer.add(this.markers);
// this.map.setFitView(null, false, [100, 150, 10, 10]); //地图缩放到合适的位置,开启每次都会缩放到最大状态
// this.toggleBtn()
},
initMap() {
AMapLoader.load({
key: "xxxx你的keyxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
"plugins": [
"AMap.Scale",
"AMap.HawkEye",
"AMap.ToolBar",
"AMap.AutoComplete",
"AMap.PlaceSearch",
"AMap.ControlBar",
"AMap.MouseTool",
"AMap.DragRoute",
"AMap.MoveAnimation"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
this.AMap=AMap
this.map = new AMap.Map("container", { //设置地图容器id
zoom: 15.8, // 初始化地图级别
center: this.center, //中心点坐标 成都 104.065735, 30.659462
showIndoorMap: false,
});
this.initMarkers(AMap);
// this.map.on('zoomend', function (e) {
// this.zoom =this.map.getZoom();
// console.log(this.zoom)
//
// }.bind(this));
}).catch(e => {
console.log(e);
})
},
},
//生命周期 - 创建完成(可以访问当前 this 实例)
created() {
this.newestPositions()
},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() {
this.timer = setInterval(this.newestPositionsWithoutInitMap, 120 * 1000);
this.initMap();
},
//生命周期 - 创建之前
beforeCreate() {
},
//生命周期 - 挂载之前
beforeMount() {
},
//生命周期 - 更新之前
beforeUpdate() {
},
//生命周期 - 更新之后
updated() {
},
//生命周期 - 销毁之前
beforeDestroy() {
clearInterval(this.timer);
},
//生命周期 - 销毁完成
destroyed() {
},
//如果页面有 keep-alive 缓存功能, 这个函数会触发
activated() {
},
}
</script>
<style scoped>
#container {
padding: 0px;
margin: 0px;
width: 100%;
height: 800px;
}
.input-item {
height: 2.2rem;
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-radius: .25rem;
width: 10rem;
border-width: 0;
border-radius: 0.4rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
position: fixed;
bottom: 12rem;
right: 2rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
}
</style>
3.2 Usage examples
Refer to 1.2, no changes
3.3 Extraction effect
The position is refreshed every 2 minutes based on the effect of 2.3