点击测距工具可以开启测量,再次点击关闭测量,清除地图上的点、连线、文字
再次点击测量工具的时候清除。
首先
上面的功能条河下面的地图我搞成了两个组件,他们作为兄弟组件存在,所以简单用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
<divonClick={()=>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 和 textthis.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 = thisvar 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 和 textthat.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 和 Textif (arr.length == 2) {that.lineAndTextFun(that, arr);}// 存储标记点that.setState({currentClickMarkerList: arr,});// mapthat.map.add(arr);});}}eventBus.$on((flag) => {this.setState({isCanClickMarkerLineFlag: flag,},() => {if (!flag) {// 清楚line 和 textthis.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.15plugins: [''], // 需要使用的的插件列表,如比例尺'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);}// 划线 和 展示 textlineAndTextFun = (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