高德地图Web端(JS API)实战使用

React H5中,高德地图API实战使用封装

一、定义封装 useDrawTraceMap:绘制轨迹地图,包括起点、终点、行车轨迹

import { useCallback, useEffect, useRef } from "react";
import AMapLoader from "@amap/amap-jsapi-loader";
import { nanoid } from "nanoid";

export interface TLatitudeLongitude {
  /**
   * 纬度
   */
  lat: number | string;
  /**
   * 经度
   */
  lng: number | string;
}

export type TDrivingTrace = Partial<{
  /**
   * 行车轨迹
   */
  drive: TLatitudeLongitude[];
  /**
   * 起点
   */
  startPoint: TLatitudeLongitude;
  /**
   * 终点
   */
  endPoint: TLatitudeLongitude;
}>;

interface DrawTraceMapProps {
  /**
   * 地图轨迹数据,包含起点、终点、行车轨迹
   */
  traceData: TDrivingTrace;
  /**
   * 是否关闭起到到终点的轨迹路线
   */
  closePolyline?: boolean;
  /**
   * 是否隐藏起点
   */
  hideStartPoint?: boolean;
  /**
   * 是否隐藏终点
   */
  hideEndPoint?: boolean;
}

interface UseDrawTraceMapProps {
  /**
   * 申请好的Web端开发者Key,要么在 hooks 里面写死 default_key,要么传值
   * 否则报错【useDrawTraceMap.ts:180 请求 AMapUI 失败】
   */
  key: string;
}

/**
 * 绘制轨迹地图,包括起点、终点、行车轨迹
 * @returns
 */
const useDrawTraceMap = (props?: UseDrawTraceMapProps) => {
  const DEFAULT_KEY = "you_apply_really_key";
  const mapInstanceRef = useRef<any>(null);
  const containerIdRef = useRef<string>(nanoid());

  const drawTraceMap = useCallback(
    async (drawProps: DrawTraceMapProps) => {
      const {
        traceData,
        closePolyline = false,
        hideStartPoint = false,
        hideEndPoint = false,
      } = drawProps;

      if (!traceData) {
        return;
      }

      await AMapLoader.load({
        key: props?.key || DEFAULT_KEY, // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "1.4.15", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: ["AMap.Autocomplete"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
        AMapUI: {
          // 是否加载 AMapUI,缺省不加载
          version: "1.1", // AMapUI 缺省 1.1
          plugins: ["overlay/SimpleMarker"], // 需要加载的 AMapUI ui插件
        },
        Loca: {
          // 是否加载 Loca, 缺省不加载
          version: "1.3.2", // Loca 版本,缺省 1.3.2
        },
      })
        .then((AMap) => {
          const startX = traceData.startPoint?.lng?.toString() || "";
          const startY = traceData.startPoint?.lat?.toString() || "";

          // 创建一个 Icon
          const startIcon = new AMap.Icon({
            // 图标尺寸
            size: new AMap.Size(25, 34),
            // 图标的取图地址
            image:
              "//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png",
            // 图标所用图片大小
            imageSize: new AMap.Size(135, 40),
            // 图标取图偏移量
            imageOffset: new AMap.Pixel(-9, -3),
          });

          // 将 icon 传入 marker
          const startMarker = new AMap.Marker({
            position: new AMap.LngLat(
              parseFloat(String(startX)),
              parseFloat(String(startY))
            ),
            icon: startIcon,
            offset: new AMap.Pixel(-13, -30),
          });

          const endX = traceData.endPoint?.lng?.toString() || "";
          const endY = traceData.endPoint?.lat?.toString() || "";

          // 创建一个 icon
          const endIcon = new AMap.Icon({
            size: new AMap.Size(25, 34),
            image:
              "//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png",
            imageSize: new AMap.Size(135, 40),
            imageOffset: new AMap.Pixel(-95, -3),
          });

          // 将 icon 传入 marker
          const endMarker = new AMap.Marker({
            position: new AMap.LngLat(
              parseFloat(String(endX)),
              parseFloat(String(endY))
            ),
            icon: endIcon,
            offset: new AMap.Pixel(-13, -30),
          });

          // 将 markers 添加到地图
          mapInstanceRef.current = new AMap.Map(containerIdRef.current, {
            center: [parseFloat(String(startX)), parseFloat(String(startY))],
            zoom: 12,
            resizeEnable: true,
            mapStyle: "amap://styles/macaron",
          });

          mapInstanceRef.current?.add([
            hideStartPoint ? null : startMarker,
            hideEndPoint ? null : endMarker,
          ]);

          // 绘制轨迹
          if (!closePolyline) {
            const path = traceData?.drive?.map((item) => {
              return [item.lng, item.lat];
            });

            /* 绘制轨迹 */
            new AMap.Polyline({
              map: mapInstanceRef.current,
              path,
              showDir: true,
              strokeColor: "#28F", // 线颜色
              // strokeOpacity: 1,     //线透明度
              strokeWeight: 6, // 线宽
              // strokeStyle: "solid"  //线样式
            });
          }

          mapInstanceRef.current.setFitView();

          // mapInstanceRef.current.on("complete", function () {
          //   mapInstanceRef.current.setFitView();
          // });
        })
        .catch((e) => {
          console.error(e); // 加载错误提示
        });
    },
    [props?.key]
  );

  const hasMapInstance = useCallback(() => {
    return !!mapInstanceRef.current;
  }, []);

  useEffect(() => {
    return () => {
      if (mapInstanceRef.current) {
        mapInstanceRef.current?.destroy?.();
      }
    };
  }, []);

  return {
    containerId: containerIdRef.current,
    drawTraceMap,
    hasMapInstance,
  } as {
    /**
     * 挂载地图的容器元素 id
     */
    containerId: string;
    /**
     * 绘制地图函数
     * @param drawProps
     * @returns
     */
    drawTraceMap: (drawProps: DrawTraceMapProps) => Promise<void>;
    /**
     * 是否有地图实例,用于判断是否已经绘制过地图
     * @returns
     */
    hasMapInstance: () => boolean;
  };
};

export default useDrawTraceMap;

二、useDrawTraceMap的使用示例

import useDrawTraceMap from "@/hooks/useDrawTraceMap";
import { useEffect } from "react";

/**
 * 广州——深圳的行车轨迹数据
 */
const traceData = {
  drive: [
    {
      lat: 23.1291,
      lng: 113.2644,
    },
    {
      lat: 23.0,
      lng: 113.5,
    },
    {
      lat: 22.9,
      lng: 113.7,
    },
    {
      lat: 22.8,
      lng: 113.9,
    },
    {
      lat: 22.7,
      lng: 114.1,
    },
    {
      lat: 22.5431,
      lng: 114.0579,
    },
  ],
  startPoint: {
    lat: 23.1291,
    lng: 113.2644,
  },
  endPoint: {
    lat: 22.5431,
    lng: 114.0579,
  },
};

const TestMap = () => {
  const { containerId, drawTraceMap } = useDrawTraceMap();

  useEffect(() => {
    drawTraceMap({
      traceData,
    });
  }, [drawTraceMap]);

  return (
    <div
      style={{
        height: "100vh",
        background: "rgb(221, 228, 235)",
        padding: "24px",
      }}
    >
      <div style={{ height: "300px" }} id={containerId} />
    </div>
  );
};

export default TestMap;

页面效果

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值