点击测距工具可以开启测量,再次点击关闭测量,清除地图上的点、连线、文字
再次点击测量工具的时候清除。
首先
上面的功能条河下面的地图我搞成了两个组件,他们作为兄弟组件存在,所以简单用js写了个事件监听触发的对象,
eventObj.js
const eventBus = {
evnetList: [],
// 监听事件
$on(callbackFun, name) {
this.evnetList.push({
name,
callbackFun
})
},
//触发事件
$emit(name, data) {
this.evnetList.forEach(element => {
if (name === element.name) {
element.callbackFun(data)
}
});
},
}
export default eventBus
我们在头部工具栏组件中引入:
import eventBus from './eventObj';
点击的dom
<div
onClick={()=>this.clickFlagFun()}
className={this.state.clickFlag ? 'rightBox1click' : 'rightBox1 '}
>
<Icon type="discount-o" style={{ marginRight: '4px' }} />
测AB间距
</div>
事件:
clickFlag: 需要再 state 中提前声明 为 false 默认为关闭
clickFlagFun() {
this.setState({
clickFlag: !this.state.clickFlag,
},()=>{
Toast.prompt({
content: this.state.clickFlag ? '已开启测量工具' : '已关闭测量工具',
duration: 5000,
size: 'large'
});
//主动触发自定义事件
eventBus.$emit('changclickFlag',this.state.clickFlag)
});
}
在地图盒子中:
我们需要在挂载的时候就进行监听这个事件:
执行相应的逻辑(这个一会说)
eventBus.$on((flag) => {
this.setState(
{
isCanClickMarkerLineFlag: flag,
},
() => {
if (!flag) {
// 清楚line 和 text
this.map.remove([
...this.state.textAndlineObj,
...this.state.currentClickMarkerList,
]);
this.setState({
currentClickMarkerList: [],
currentClickOptionsList: [],
textAndlineObj: [],
});
this.map.off('click', clickHandler);
return false;
}
// 测量距离方法
flag && this.map.on('click', clickHandler);
}
);
}, 'changclickFlag');
看地图组件全部代码,里面有对应注释(其实代码很low 但是不想整理 因为它能跑):
import React, { Component } from 'react';
import { Icon } from '@alife/aisc';
import AMapLoader from '@amap/amap-jsapi-loader';
import '../index.scss';
import eventBus from './eventObj';
import { base64PNG, sanjiaoSVG, gray, red, green } from './base64png.js';
const content = `<div style="width:auto;padding:3px;background:gray;color:#000;border:none">EU126,租凭<br/>XX.XX MW</div>`;
class MapComponent extends Component {
constructor() {
super();
this.map = {};
this.AMap = null;
this.state = {
isCanClickMarkerLineFlag: false,
zoom: 10,
datalist: [
{
icon: 1,
position: [121.487899486, 31.24916171],
title: 'aaaaa',
zoom: 3,
content,
},
{
icon: 2,
position: [121.287899486, 31.34916171],
title: 'bbb',
zoom: 3,
content,
},
{
icon: 3,
position: [121.387899486, 31.44916171],
title: 'ccc',
zoom: 3,
content,
},
{
icon: 3,
position: [121.487899486, 31.44916171],
title: 'ddd',
zoom: 3,
content,
},
{
icon: 3,
position: [121.487899486, 31.54916171],
title: 'eee',
zoom: 3,
content,
},
],
currentClickMarkerList: [],
currentClickOptionsList: [],
textAndlineObj: [],
};
}
// 2.dom渲染成功后进行map对象的创建
componentDidMount() {
const that = this
var clickHandler = function (e) {
// 最多生成两个标记点
if (that.state.currentClickOptionsList.length <= 2) {
let arrList = [];
// 只能点击两个坐标
if (that.state.currentClickOptionsList.length !== 0) {
// 第一个 + 第二个标记点坐标
arrList = [
that.state.currentClickOptionsList[0],
[e.lnglat.getLng(), e.lnglat.getLat()],
];
} else {
// 第一标记点坐标
arrList = [[e.lnglat.getLng(), e.lnglat.getLat()]];
}
// 为了避免重复渲染
// 清楚line 和 text
that.map.remove([
...that.state.textAndlineObj,
...that.state.currentClickMarkerList,
]);
that.setState(
{
// 坐标存起来 目前没有用到 只是做长度判断使用
currentClickOptionsList: arrList,
},
() => {
// 循环生成点击两次的坐标点
const currentClickOptionsList = arrList;
let arr = [];
currentClickOptionsList.map((i, idx) => {
var marker1 = new AMap.Marker({
icon: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
position: new AMap.LngLat(i[0], i[1]),
zoom: 888,
// 是否拖拽
draggable: true,
// clickable: true,
extData: {
flag: idx,
},
// 图标大小
offset: [-10, -31],
});
// 存起来两个标点对象
arr = [...arr, marker1];
});
// 标点对象为两个的时候 展示 line 和 Text
if (arr.length == 2) {
that.lineAndTextFun(that, arr);
}
// 存储标记点
that.setState({
currentClickMarkerList: arr,
});
// map
that.map.add(arr);
}
);
}
}
eventBus.$on((flag) => {
this.setState(
{
isCanClickMarkerLineFlag: flag,
},
() => {
if (!flag) {
// 清楚line 和 text
this.map.remove([
...this.state.textAndlineObj,
...this.state.currentClickMarkerList,
]);
this.setState({
currentClickMarkerList: [],
currentClickOptionsList: [],
textAndlineObj: [],
});
this.map.off('click', clickHandler);
return false;
}
// 测量距离方法
flag && this.map.on('click', clickHandler);
}
);
}, 'changclickFlag');
AMapLoader.reset(); //需要把这个reset一下
AMapLoader.load({
key: 'xxxxxxxxxxxxxx', // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
console.log(AMap, 'AMap');
this.AMap = AMap;
this.renderMapFun();
})
.catch((e) => {
console.log(e);
});
}
renderMapFun() {
// 生成容器
this.map = new this.AMap.Map('container111', {
zoom: this.state.zoom, //初始化地图级别
center: [121.487899486, 31.24916171], //初始化地图中心点位置-上海
});
const obj = {
1: green,
2: red,
3: gray,
};
// 生成 默认点
let arr = [];
this.state.datalist.map((i) => {
var marker1 = new AMap.Marker({
icon: obj[i.icon],
position: i.position,
title: i.title,
zoom: i.zoom,
});
marker1.setLabel({
content: i.content,
offset: new AMap.Pixel(-20, 28),
});
arr = [...arr, marker1];
});
this.map.add(arr);
}
// 划线 和 展示 text
lineAndTextFun = (that, arr) => {
var line = new AMap.Polyline({
strokeColor: '#80d8ff',
isOutline: true,
outlineColor: 'white',
});
that.map.add(line);
var text = new AMap.Text({
text: '',
style: {
'background-color': '#29b6f6',
'border-color': '#e1f5fe',
'font-size': '12px',
},
});
function computeDis() {
var p1 = arr[0].getPosition();
var p2 = arr[1].getPosition();
var textPos = p1.divideBy(2).add(p2.divideBy(2));
var distance = Math.round(p1.distance(p2));
var path = [p1, p2];
line.setPath(path);
text.setText('两点相距' + distance + '米');
text.setPosition(textPos);
}
computeDis();
arr[0].on('dragging', computeDis);
arr[1].on('dragging', computeDis);
that.map.add(text);
that.setState({
textAndlineObj: [text, line],
});
};
addFun = () => {
const { zoom } = this.state;
if (zoom !== 18) {
this.setState(
{
zoom: zoom + 1,
},
() => {
// 设置地图显示的缩放级别,在PC上,参数zoom可设范围:[3,18];
// 在移动端:参数zoom可设范围:[3,19]。3D地图下,可将zoom设置为浮点数。/
this.map.setZoom(this.state.zoom);
}
);
}
};
downFun = () => {
const { zoom } = this.state;
if (zoom !== 3) {
this.setState(
{
zoom: zoom - 1,
},
() => {
this.map.setZoom(this.state.zoom);
}
);
}
};
render() {
// 1.初始化创建地图容器,div标签作为地图容器,同时为该div指定id属性;
return (
<div style={{ width: '100%', height: '100%' }}>
<div id="container111" className="map">
<div className="leftBox">
<div className="top">
<Icon type="add" onClick={this.addFun} />
{this.state.zoom} <Icon type="minus" onClick={this.downFun} />
</div>
<div className="bottom">
<div className="box">
<img src={gray} alt="" />
预计裁撤
</div>
<div className="box">
<img src={red} alt="" />
建设中
</div>
<div className="box">
<img src={green} alt="" />
预计保留
</div>
</div>
</div>
</div>
</div>
);
}
}
//导出地图组建类
export default MapComponent;
总结一下吧:
1、点击开启测距
2、点出两个距离点的时候展示测出的距离描述(Line、Text)
3、再点击其他区域,会再次生成一个新的
4、可以实现拖拽效果,重新测出距离
5、再次点击开始测距,关闭,同时清除map上的距离点、line、text。
看的有点蒙的话 可以先看看前两篇:
一、前端高德地图注册、项目中引入、渲染标记(Marker)and覆盖物(Circle)
二、前端高德地图、渲染标记(Marker)引入自定义icon,手动设置zoom
另外献上官方连接:
1、https://lbs.amap.com/demo/javascript-api/example/map-componets/map-overlays
2、https://lbs.amap.com/demo/javascript-api/example/event/map-click-event
3、https://lbs.amap.com/demo/javascript-api/example/event/event-map-drag