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