高德地图很强大,涉及到地图相关的功能都有,连天气预报都开放了API,真心好用。

下面列举一些用车相关的功能示例,基本跟官方示例是一致的,部分有出入。

1、初始化

安装地图插件

npm i @amap/amap-jsapi-loader --save

使用示例

import AMapLoader from '@amap/amap-jsapi-loader';

AMapLoader.load({
    "key": "",              // 申请好的Web端开发者Key,首次调用 load 时必填
    "version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    "plugins": [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap)=>{
    map = new AMap.Map('container');
}).catch(e => {
    console.log(e);
})

初始化window参数

window._AMapSecurityConfig = {
    securityJsCode: aMapSecrectKey //安全密钥 路径规划要用
}
// JSAPI 默认启用了 failIfMajorPerformanceCaveat 参数来获取 webgl 上下文,图形绘制性能比较差的环境下不开启WebGL绘制,
// 如需要可以在 地图 JSAPI 脚本引用之前设置全局变量 window.forceWebGL = true;
// 高德地图2.0以上版本要求浏览器支持webgl才能修改style
window.forceWebGL = true;

初始化地图

建议将AMap、map挂载在window上,之后都使用同一个AMap、map。

            const AMap = await AMapLoader.load({
                key: aMapKey,                // 申请好的Web端开发者Key,首次调用 load 时必填
                version: '2.0',              // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                plugins: [''],               // 需要使用的的插件列表,如比例尺'AMap.Scale'等
                viewMode: '2D'
            });
            const map = new AMap.Map('container', {
                zoom: 16, //初始化地图级别
                center: [116.397428, 39.90923],
                resizeEnable: true,
                mapStyle: "amap://styles/whitesmoke"
            })
            window.AMap = AMap
            window.map = map

2、画标记点

const content =
      `
    <div class="map-tips-root">
    ` +
      popLayout +
      markImg +
      `
    </div>`;
const marker = new AMap.Marker({
      content: content, // 自定义点标记覆盖物内容
      position: position, // 基点位置
      angle: angle,
      // draggable: true, //是否可拖拽
      // cursor: 'move',
    });
map.add(marker);

content可以根据你的需求写html代码,也可以指定样式,如:

.map-tips-root {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    transform: translate3d(-50%, -50%, 0);
}

3、定位


    const map = window.map;
    const AMap = window.AMap;
    AMap.plugin('AMap.Geolocation', function () {
      const geolocation = new AMap.Geolocation({
        enableHighAccuracy: true, //是否使用高精度定位,默认:true
        timeout: 10000, //超过10秒后停止定位,默认:5s
        position: 'RB', //定位按钮的停靠位置
        offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
        zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
      });
      map.addControl(geolocation);
      geolocation.getCurrentPosition(function (status, result) {
        if (status === 'complete') {
          onComplete(result);
          onMapLocation(result);
        } else {
          onMapLocation({});
          onError(result);
        }
      });
    });
    //解析定位结果
    function onComplete(data) {
      console.log('当前定位信息:data', data);
      // document.getElementById('status').innerHTML='定位成功'
      const str: any[] = [];
      str.push('定位结果:' + data.position);
      str.push('定位类别:' + data.location_type);
      if (data.accuracy) {
        str.push('精度:' + data.accuracy + ' 米');
      } //如为IP精确定位结果则没有精度信息
      str.push('是否经过偏移:' + (data.isConverted ? '是' : '否'));

      console.log('当前定位信息:', str);
      // document.getElementById('result').innerHTML = str.join('<br>');
    }
    //解析定位错误信息
    function onError(data) {
      console.log('当前定位失败:', data);
      // document.getElementById('status').innerHTML='定位失败'
      // document.getElementById('result').innerHTML = '失败原因排查信息:'+data.message+'</br>浏览器返回信息:'+data.originMessage;
    }

4、路径规划


      //根据经纬度规划路经
      AMap.plugin('AMap.Driving', function () {
        const driving = new AMap.Driving({
          // 驾车路线规划策略,AMap.DrivingPolicy.LEAST_TIME是最快捷模式
          policy: AMap.DrivingPolicy.LEAST_TIME,
          // map 指定将路线规划方案绘制到对应的AMap.Map对象上
          map: map,
          hideMarkers: true, //设置隐藏路径规划的起始点图标,设置为true:隐藏图标;设置false:显示图标
          // panel 指定将结构化的路线详情数据显示的对应的DOM上,传入值需是DOM的ID
          // panel: 'panel'
        });
        lastDriving.current = driving;
        //todo 模拟司机在起点位置,后面修改成司机实时位置
        const startLngLat = [driverLng, driverLat];
        // const startLngLat = [startEndLngLat.start.lng, startEndLngLat.start.lat];
        const endLngLat = [startEndLngLat.end.lng, startEndLngLat.end.lat];
        driving.search(startLngLat, endLngLat, function (status, result) {
          console.log('testDriving status,result', status, result);

          if (status === 'complete') {
            let popTips;
            if (result.routes && result.routes.length > 0) {
              // const dis = result.routes[0].distance || 0;
              // const time = result.routes[0].time || 0;

              const distance = result.routes[0].distance || 0;
              const isFast = distance < 1000;
              let distanceAfter = distance >= 1000 ? distance / 1000 : distance;
              distanceAfter = distanceAfter.toFixed(1);
              let time = result.routes[0].time || 0;
              time = time / 60;
              time = parseInt(time);
              time = time < 1 ? 1 : time;
              //todo 添加即将到达逻辑,小于一公里显示“即将到达”
              if (isFast) {
                if (!isEnding.current) {
                  isEnding.current = true;
                  mapUpdateState(OrderState.serviceEnding);
                }
              }
              popTips = isFast
                ? {
                    oneTip: '即将到达',
                  }
                : {
                    moreTip: {
                      // normal1: '距您',
                      highLight1: distanceAfter,
                      normal2: '公里',
                      highLight2: time,
                      normal3: '分钟',
                    },
                  };
            }
            if (driverLng && driverLat) {
              //先画汽车
              testMarkLayoutReal(
                AMap,
                map,
                [driverLng, driverLat],
                getMarkCar(),
                null,
                driverAngle,
              );
              //再画气泡
              testMarkLayoutReal(AMap, map, [driverLng, driverLat], getMarkCarAlpha0(), popTips);
            }
          }
        });
      });
    }

5、轨迹回放

const lineArr = [
        [116.478935, 39.997761],
        [116.478939, 39.997825],
        [116.478912, 39.998549],
        [116.478912, 39.998549],
        [116.478998, 39.998555],
        [116.478998, 39.998555],
        [116.479282, 39.99856],
        [116.479658, 39.998528],
        [116.480151, 39.998453],
        [116.480784, 39.998302],
        [116.480784, 39.998302],
        [116.481149, 39.998184],
        [116.481573, 39.997997],
        [116.481863, 39.997846],
        [116.482072, 39.997718],
        [116.482362, 39.997718],
        [116.483633, 39.998935],
        [116.48367, 39.998968],
        [116.484648, 39.999861],
      ];
AMap.plugin('AMap.MoveAnimation', function () {
        const lineArr = orderDetailInfo.drivingRoads.map((item) => {
          return [item.lng, item.lat];
        });
        console.log('drawPay lineArr', lineArr);
        const marker = new AMap.Marker({
          map: map,
          position: [116.478935, 39.997761],
          content: getMarkCar(),
          offset: new AMap.Pixel(-13, -26),
        });

        // 绘制轨迹
        const passedPolyline = new AMap.Polyline({
          map: map,
          // path: lineArr,
          showDir: true,
          strokeColor: '#C7C7C7', //线颜色
          strokeOpacity: 1, //线透明度
          strokeWeight: 6, //线宽
          strokeStyle: 'solid', //线样式
        });
        marker.on('moving', function (e) {
          passedPolyline.setPath(e.passedPath);
          map.setCenter(e.target.getPosition(), true);
        });

        // map.setFitView();

        marker.moveAlong(lineArr, {
          // 每一段的时长
          duration: 500, //可根据实际采集时间间隔设置
          // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
          autoRotation: true,
        });
      }

6、拖动选址

拖动标记点获取位置(拖动选址)

 marker.on('dragend', function (e) 
const marker = testMarkLayoutReal(
          AMap,
          map,
          [startEndLngLat.start.lng, startEndLngLat.start.lat],
          getMarkStart(),
          popTips,
        );
        // map.setZoomAndCenter(14, [121.457054, 31.183843]);
        map.setZoomAndCenter(14, [startEndLngLat.start.lng, startEndLngLat.start.lat]);
        marker.setCursor('move');
        marker.setDraggable(true);
        marker.on('dragend', function (e) {
          //拖拽标记 更新经纬度
          const lat = e.lnglat.lat;
          const lng = e.lnglat.lng;
          console.log('dragend ...lat,lng', lat, lng);

          const lnglatXY = [lng, lat]; //地图上所标点的坐标
          AMap.plugin('AMap.Geocoder', function () {
            //回调函数
            const geocoder = new AMap.Geocoder({});
            geocoder.getAddress(lnglatXY, function (status, result) {
              if (status === 'complete' && result.info === 'OK') {
                //获得了有效的地址信息:
                console.log('AMap.Geocoder result', result);
                const formattedAddress =
                  (result && result.regeocode && result.regeocode.formattedAddress) || '';
                let subAddress = '';
                const indexOf = (formattedAddress && formattedAddress.indexOf('街道')) || 0;
                if (indexOf >= 0) {
                  subAddress =
                    formattedAddress.length > indexOf + 2 &&
                    formattedAddress.substring(indexOf + 2, formattedAddress.length);
                }
                console.log('AMap.Geocoder subAddress', subAddress);

                onUpdateSearch({
                  ...onSearch,
                  startPoint: {
                    name: subAddress,
                    location: {
                      lat: lat,
                      lng: lng,
                    },
                  },
                });
              } else {
                //获取地址失败
              }
            });
          });
        });

7、点击标记点响应

        const marker = testMarkLayoutReal(
          AMap,
          map,
          [startEndLngLat.end.lng, startEndLngLat.end.lat],
          getMarkEnd(),
          popTips,
        );
        map.setZoomAndCenter(14, [startEndLngLat.end.lng, startEndLngLat.end.lat]);
        marker.setCursor('move');
        marker.setDraggable(true);
        marker.on('click', function (e) {
          //点击标记 去搜索页
          console.log('click ... ', e);
        });

testMarkLayoutReal:

  const testMarkLayoutReal = (AMap, map, position: number[], markImg, popTips: any, angle?) => {
    const content = getMarkContent(markImg, popTips);
    const marker = new AMap.Marker({
      content: content, // 自定义点标记覆盖物内容
      position: position, // 基点位置
      angle: angle,
    });
    map.add(marker);
    return marker;
  };

getMarkContent:

  const getMarkContent = (markImg, popTips: any) => {
    // popTips = {
    //   oneTip: '上海平安大厦',
    //   rightIcon: require('../Image/map_tips_right_arrow.png'),
    //   moreTip: {
    //     normal1: '距您',
    //     highLight1: '1.7',
    //     normal2: '公里',
    //     highLight2: '11',
    //     normal3: '分钟',
    //   },
    // };
    // const markImg = require('../Image/map_location_start.png');
    // const imgStr = '<img  class="map-mark-start-end"  src="' + markImg + '"/>';
    const tipsIcon = require('../Image/map_tips_arrow.png');
    const tipsIconStr = '<img class="map-tips-pop-arrow" src="' + tipsIcon + '"/>';

    let popLayout = '';
    if (popTips) {
      const oneTip = getNormalSpan(popTips.oneTip);
      let normal1 = '';
      let normal2 = '';
      let normal3 = '';
      let highLight1 = '';
      let highLight2 = '';
      if (!oneTip && popTips.moreTip) {
        normal1 = getNormalSpan(popTips.moreTip.normal1);
        normal2 = getNormalSpan(popTips.moreTip.normal2);
        normal3 = getNormalSpan(popTips.moreTip.normal3);
        highLight1 = getHighLightSpan(popTips.moreTip.highLight1);
        highLight2 = getHighLightSpan(popTips.moreTip.highLight2);
      }

      // const tipsRightArrow = require('../Image/map_tips_right_arrow.png');
      const rightIcon = popTips.rightIcon
        ? '<img class="map-tips-pop-right-arrow" src="' + popTips.rightIcon + '"/>'
        : '';
      popLayout =
        popTips &&
        `
      <div class="map-tips-pop">
        <div class="map-tips-pop-row">
        ` +
          oneTip +
          normal1 +
          highLight1 +
          normal2 +
          highLight2 +
          normal3 +
          rightIcon +
          `
        </div>
        ` +
          tipsIconStr +
          `
      </div>`;
    }

    const content =
      `
    <div class="map-tips-root">
    ` +
      popLayout +
      markImg +
      `
    </div>`;
    return content;
  };

markImg:

  const getMarkStart = () => {
    return (
      '<img  class="map-mark-start-end"  src="' +
      require('../Image/map_location_start.png') +
      '"/>\n'
    );
  };
  markImg = getMarkStart();