三、前端高德地图、测量两个点之前的距离

点击测距工具可以开启测量,再次点击关闭测量,清除地图上的点、连线、文字

三、前端高德地图、测量两个点之前的距离_第1张图片

三、前端高德地图、测量两个点之前的距离_第2张图片

再次点击测量工具的时候清除。

首先

上面的功能条河下面的地图我搞成了两个组件,他们作为兄弟组件存在,所以简单用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 = `
EU126,租凭
XX.XX MW
`
; 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="" /> xxxx </div> <div className="box"> <img src={red} alt="" /> xxxx </div> <div className="box"> <img src={green} alt="" /> xxxx </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

你可能感兴趣的:(高德地图,前端,高德地图)