3. Front-end Gaode map, measure the distance between two points

Click the distance measurement tool to start the measurement, click it again to close the measurement, and clear the points, lines, and text on the map

insert image description here
insert image description here

Cleared when the measure tool is clicked again.

first

The above function bar and the map below I made two components, they exist as sibling components, so simply use js to write an object for event monitoring and triggering,
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

We introduce in the header toolbar component:

import eventBus from './eventObj';

clicked dom

<div
   onClick={
    
    ()=>this.clickFlagFun()}
   className={
    
    this.state.clickFlag ? 'rightBox1click' : 'rightBox1 '}
 >
   <Icon type="discount-o" style={
    
    {
    
     marginRight: '4px' }} />AB间距
 </div>

Event:
clickFlag: It needs to be declared as false in the state in advance, and it is closed by default

  clickFlagFun() {
    
    
    this.setState({
    
    
      clickFlag: !this.state.clickFlag,
    },()=>{
    
    
      Toast.prompt({
    
    
        content: this.state.clickFlag ? '已开启测量工具' : '已关闭测量工具',
        duration: 5000,
        size: 'large'
      });
      //主动触发自定义事件
      eventBus.$emit('changclickFlag',this.state.clickFlag)
    });
  }

In the map box:
we need to listen to this event when mounting:
execute the corresponding logic (this will be discussed later)

    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');

Look at the entire code of the map component, there are corresponding comments in it (in fact, the code is very low, but I don’t want to tidy it up because it can run):

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;

Let’s sum it up:
1. Click to enable distance measurement
2. Display the measured distance description (Line, Text) when two distance points are clicked
3. Click another area to generate a new one again
4. Drag and drop can be realized Effect, re-measure the distance
5. Click again to start distance measurement, close, and clear the distance point, line, and text on the map at the same time.

If you are a bit confused, you can read the first two articles first:
1. Front-end Gaode map registration, import in the project, rendering marker (Marker) and coverage (Circle)
2. Front-end Gaode map, rendering marker (Marker) import from Define icon, manually set 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

Guess you like

Origin blog.csdn.net/qq_43291759/article/details/132015721