Next.js 中 导入 高德地图 AMap

在高德的官方文档中,只有对 React 的引用,虽说Next.js是React的一个框架,但按照官方文档,真的会失败,并且一直报错。摸摸索索后,终于成功了,记录一下这次的成功过程,希望也能解决你目前遇到的问题

1. 按 NPM 方式安装使用Amap Loader

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

2. 在项目中使用

在搜索解决报错问题时,也有幸看见了 nextjs 接入高德地图? 原来有人也跟我一样

/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useRef, useState } from "react";
import "./body.css";

export function BodyMap() {
  const mapRef = useRef < HTMLDivElement > (null);
  const [amapLoaded, setAmapLoaded] = useState(false)

  useEffect(() => {

    if (typeof window !== 'undefined') {
      import('@amap/amap-jsapi-loader').then(AMapLoader => {
        AMapLoader.load({
          key: '你的key值',
          version: '2.0',
          Loca: { // 是否加载 Loca, 缺省不加载
            version: '2.0.0' // Loca 版本,缺省 1.3.2
          },
        }).then((AMap) => {
          setAmapLoaded(true);
          const map = new AMap.Map(mapRef.current, {
            // 设置地图容器id
            viewMode: '3D', // 是否为3D地图模式
            zoom: 5, // 初始化地图级别
            center: [105.602725, 22.076636], // 初始化地图中心点位置
          });
        });
      })
    }
  }, []);
  return ( 
    <div className = "map_body" >
      <div ref = {mapRef} id = "container" > </div>
    </div>
  );
}

当然,地图的宽与高不能忘了设置,不然也无法显示

#container {
    padding: 0px;
    margin: 0px;
    width: 100%;
    height: 100%;
}

3. 使用 DistrictLayer

有了上面的例子,但还是不太满足我对行政区块划分并着色的需求,看着官网上的 行政区块拾取+修改样式 这个就比较满足我的需要求了,具体使用如下:

// 绘制世界地图国家轮廓
const distWorld = new AMap.DistrictLayer.World({
    zIndex: 10,
    styles: {
        'nation-stroke': 'rgb(225, 103, 255)',
        'province-stroke': 'rgb(103, 194, 255)',
        'city-stroke': 'rgba(103, 255, 111, 1)',
    }
});


const map = new AMap.Map(mapRef.current, {
    zooms: [2, 4],
    center: [110, 30],
    showIndoorMap: false,
    zoom: 3,
    isHotspot: false,
    defaultCursor: 'pointer',
    touchZoomCenter: 1,
    pitch: 0,
    layers: [
        distWorld,
    ],
    viewMode: '3D',
});

// 添加点击事件
map.on('click', function (ev: any) {
    var px = ev.pixel;
    // 拾取所在位置的行政区
    var props = distWorld.getDistrictByContainerPos(px);

    if (props) {
        var SOC = props.SOC;
        if (SOC) {
            // 重置行政区样式
            distWorld.setStyles({
                // 国境线
                'nation-stroke': 'rgb(225, 103, 255)',
                'province-stroke': 'rgb(103, 194, 255)',
                'city-stroke': 'rgba(103, 255, 111, 1)',
                'fill': function (props: any) {
                    return props.SOC == SOC ? 'rgb(251, 255, 9)' : 'white';
                }
            });
        }
    }
});

显示 到 市级 的话,使用 DistrictLayer.Country 就可以了,但这里需要注明使用的国家,并且 在distWorld.getDistrictByContainerPos(px) 中获取到我国的名称参数,与国外的是不一样的,比如,我国的参数中有 adcode 这个就可以获取到 市级的代码,但点击国外的就没有这个参数,而是 NR_C_ID

加入DistrictLayer.Country 后的代码

/* eslint-disable react-hooks/exhaustive-deps */
import {
  useEffect,
  useRef,
  useState
} from "react";
import "./body.css";

export function BodyMap() {
  const mapRef = useRef < HTMLDivElement > (null);
  const [amapLoaded, setAmapLoaded] = useState(false)

  useEffect(() => {

    if (typeof window !== 'undefined') {
      import('@amap/amap-jsapi-loader').then(AMapLoader => {
        AMapLoader.load({
          key: '你的key值',
          version: '2.0',
          Loca: { // 是否加载 Loca, 缺省不加载
            version: '2.0.0' // Loca 版本,缺省 1.3.2
          },
        }).then((AMap) => {
          setAmapLoaded(true);
          let SOC = 'CHN';
          const colors = {
            nationStroke: 'rgb(225, 103, 255)',
            provinceStroke: 'rgb(103, 194, 255)',
            cityStroke: 'rgba(103, 255, 111, 1)',
            fill: 'rgb(251, 255, 9)',
          }

          const distMap: any = {
            CHN: new AMap.DistrictLayer.Country({
              SOC: 'CHN',
              depth: 2,
              zIndex: 10,
              styles: {
                // 颜色格式: #RRGGBB、rgba()、rgb()、[r, g, b, a]
                // 国境线
                'nation-stroke': colors.nationStroke,
                'province-stroke': colors.provinceStroke,
                'city-stroke': colors.cityStroke,
              }
            }),
            MNG: new AMap.DistrictLayer.Country({
              SOC: 'MNG',
              depth: 1,
              zIndex: 10,
              styles: {
                // 国境线
                'nation-stroke': colors.nationStroke,
                'province-stroke': colors.provinceStroke,
                'city-stroke': colors.cityStroke,
              }
            }),
            RUS: new AMap.DistrictLayer.Country({
              SOC: 'RUS',
              depth: 1,
              zIndex: 10,
              styles: {
                // 国境线
                'nation-stroke': colors.nationStroke,
                'province-stroke': colors.provinceStroke,
                'city-stroke': colors.cityStroke,
              }
            }),
          }

          // 绘制世界地图国家轮廓
          const distWorld = new AMap.DistrictLayer.World({
            zIndex: 10,
            styles: {
              'nation-stroke': colors.nationStroke,
              'province-stroke': colors.provinceStroke,
              'city-stroke': colors.cityStroke,
            }
          });


          const map = new AMap.Map(mapRef.current, {
            zooms: [2, 4],
            center: [110, 30],
            showIndoorMap: false,
            zoom: 3,
            isHotspot: false,
            defaultCursor: 'pointer',
            touchZoomCenter: 1,
            pitch: 0,
            layers: [
              distWorld,
              distMap.CHN,
              distMap.MNG,
              distMap.RUS,
            ],
            viewMode: '3D',
          });

          map.on('click', function (ev: any) {
            var px = ev.pixel;
            // 拾取所在位置的行政区
            var props = distWorld.getDistrictByContainerPos(px);
            if (Object.keys(distMap).includes(props.SOC)) {
              SOC = props.SOC;
              props = distMap[SOC].getDistrictByContainerPos(px);
            }

            if (props) {
              var adcode = (props.SOC == 'CHN' ? props.adcode : props.NR_C_ID);
              var SOC2 = props.SOC;
              if (adcode) {
                // 重置行政区样式
                distMap[SOC].setStyles({
                  // 国境线
                  //nation-stroke': nationStroke,
                  'nation-stroke': colors.nationStroke,
                  'province-stroke': colors.provinceStroke,
                  'city-stroke': colors.cityStroke,
                  // 海岸线
                  //'coastline-stroke': '',
                  'fill': function (props2: any) {
                    if (props2.SOC == 'CHN') {
                      return props2.adcode == adcode ? colors.fill : 'white';
                    } else {
                      return props2.NR_C_ID == adcode ? colors.fill : 'white';
                    }
                  }
                });
              } else if (SOC2) {
                // 重置行政区样式
                distWorld.setStyles({
                  // 国境线
                  'nation-stroke': colors.nationStroke,
                  'province-stroke': colors.provinceStroke,
                  'city-stroke': colors.cityStroke,
                  'fill': function (props2: any) {
                    return props2.SOC == SOC2 ? colors.fill : 'white';
                  }
                });
              }
            }
          });
        });
      })
    }
  }, []);
  return ( 
    <div className = "map_body" >
      <div ref = {mapRef} id = "container" > </div>
    </div>
  );
}

4. 最后运行效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归尘-灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值