Google map amap usage tutorial, detailed version, universal for react and vue

My framework is vite + react. In fact, vue is almost the same.

1. Preliminary work

First go to the official website to apply for a key, address: Amap Open Platform | Amap Map API

Log in first and then enter the console

 Then open the application management, My Applications

 Then create a new application

 After the new creation is completed, create the key

 Then

After the submission is completed, you can get the key. If you need authentication at the beginning, just authenticate it. 

2. Install amap

Can be installed with npm or yarn

npm install @amap/amap-jsapi-loader

Then officially start writing code

3. Introduction and use of amap components (react version)

import AMapLoader from "@amap/amap-jsapi-loader";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import { renderToString } from "react-dom/server";

//设置在外面,方便调用
let amap;
let infoWindow;
//测试数据
//数据
let markersDate = [
    {
    id: 1,
    text: "测试1",
    position: [108.971179, 34.29238],
  },
  {
    id: 2,
    text: "测试2",
    position: [108.976082, 34.295203],
]
//自定义样式
function cameraCard() {
  //创建一个div
  const container = document.createElement("div");
  //编写html代码,样式自己写class,vue也是同理
  const vnode = (
    <div className="imgBox">
      <img className="mapicon" src={} alt="" />
    </div>
  );
  const root = createRoot(container);
  //创建注册节点
  root.render(vnode);
  return container;
}
//自定义窗体,没有啥交互可以这样写,如果有交互,还得使用render注册
function mapCard() {
  const sort = <div className="mapCardBox"></div>;
  const vnode = (
    <div
      id="mapCardBox"
      className="amap-label dashboard-borderbox-wrap amapLocation"
    >
      我是窗体1
    </div>
  );
  //转成字符串
  return renderToString(vnode);
}

//点击后的自定义窗口
function  VideoCard(){
    const container = document.createElement("div");
    const vnode = (
      <div className="videoBox">
       我是窗体222
      </div>
    );
    const root = createRoot(container);
    root.render(vnode);
    return container;
}
//窗口关闭方法,目前还没调用
//关闭
function closeInfoWindow(){
  infoWindow.close();
};

//主函数
function Map() {
   //地图样式,如果没有可以删除
   const G4 = {
     default: "amap://styles/*****************",
     dark: "amap://styles/*****************",
   };
   const mapStyle = G4.default
   
   const initMap = () => {
    AMapLoader.load({
      key: "********************", // 申请好的Web端开发者Key,首次调用 load 时必填
      version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
      plugins: [
        "AMap.MouseTool",
        "AMap.Geolocation",
        "AMap.Geocoder",
        "AMap.MarkerClusterer",
        "AMap.PlaceSearch",
        "AMap.Weather",
        "AMap.GeometryUtil",
        "AMap.Weather",
      ], //插件列表
    })
      .then((AMap) => {
        //下面这个mapContainer是id
        amap = new AMap.Map("mapContainer", {
          mapStyle: mapStyle,//设置自己的地图模式,如果没有可以删除
          resizeEnable: true,
          rotateEnable: false,
          pitchEnable: true,
          zoom: 16,//进入页面的默认值值
          pitch: 50,//倾斜角度
          rotation: 0,
          viewMode: "3D",//切换2D模式
          expandZoomRange: true,
          zooms: [6, 20],//设置视图最小值和最大值
          center:  [108.946651, 34.222718], //初始化地图中心点位置
          showLabel: true,
        });
        //遍历添加标注点位,如果只有一个,不用遍历即可
        markersDate.forEach(function (item) {
            let marker = new AMap.Marker({
                position: item.position,//坐标
                ofzzfset: new AMap.Pixel(0, 0),//点位偏移度
                visible: true,
                content: mapIcon(),//自定义点位样式,写jsx格式,方法在上面
                label: {
                  content: mapCard(),//自定义窗体,不需要可以删除该行,这里有个坑,需要是string的,所以需要用renderToString 来转
                  direction: "left",//窗体位置
                  offset: new AMap.Pixel(0, 30),//偏移位置
                },
              }); 
              //添加点击方法,item是数组数据
              marker.on("click", (evt) => showInfoM(item, evt));
              //添加点位
              amap.add(marker);
        })
        //点击事件
        function showInfoM(item, evt) {
          //打开弹窗窗口
          openInfoWindow(evt.target._position, item);
        }
        //打开窗口
        function openInfoWindow(pos, item) {
          infoWindow = new AMap.InfoWindow({
            content: VideoCard(), // 使用默认信息窗体框样式,显示信息内容,jsx格式
            offset: new AMap.Pixel(40, 40),//偏移位置
            anchor: "none",
            isCustom: true,
            // closeWhenClickMap: true, //点外部地图关闭
            retainWhenClose: true,
          });
          //打开窗口,pos == evt.target._position,是传进来的参数
          infoWindow.open(amap, pos);
        }
        //自动会集中在各个点位的中心点
        //根据地图上添加的标记或覆盖物的位置,自动调整地图的缩放级别和中心点
        amap.setFitView();
        //amap.remove(markerList[e]);
         
      })
      .catch((e) => {
        console.log(e);
      });
  };

  //初始化地图,react钩子函数,类似vue的生命周期
  useEffect(() => {
    //地图的方法
    initMap();
  }, []);
  

  return (
      <div id="mapContainer" style={
   
   { width:'100vw',height:'100vh';}}></div>
  );
   
}
export default Map;

3. Delete points and add points

If you need to hide or delete points, use  amap.remove (array to be deleted)

 amap.remove([]);//[]是需要删除的数组,这也是为什么我需要把amap定义在函数外面的原因,因为删除更新我都需要用到amap

 [] is the array that needs to be deleted, which is why I need to define amap outside the function, because I need to use amap to delete and update.

If there are multiple array points that are added, deleted, modified and checked, it is also easy to solve.

Same reason

let list1= [
    {
        id:1,
        name:"hh"
    }
]
//定义个数组
let arr = []
//存进来这个,可以用来清空指定的数组
let markerList = [[][]]


//这个onfun是一个点击事件,作用于就是点那个按钮就显示那个数组里面的内容一样,e是个number,data是外部传入的一个数组,如<div onclick={()=>{onfun(0,list1)}}>点击</div> 这样
const onfun = (e,data)=>{
 arr[e] = data 
 //这个是新增,这块最好也加个判断条件,是新增还是删除
 if(判断条件){
      //新增
      arr[e].forEach(function (item: any) {
              let marker = new AMap.Marker({
                position: item.position,
                ofzzfset: new AMap.Pixel(0, 0),
                visible: true,
                content: mapIcon(item),
                label: {
                  content: mapCard(),
                  direction: "left",
                  // offset: new AMap.Pixel(0, 30),
                },
                // content:marker.content
              });
              //存入数组之中
              markerList[e].push(marker);
              //绑定点击事件
              marker.on("click", (evt: any) => console.log("点击了"));
              amap.add(marker);
            });
   }else{
      //这个是删除,清空指定的数组
      amap.remove(markerList[e]);
      //关闭窗口
      infoWindow.close();
      //初始化数组
      markerList[e] = [];
    }
  
} 


 

4. Things to note when updating react arrays

If it is react, you need to use the useState() hook function, and then there are things you need to pay attention to when using useState(), such as

 //这里定义是一个数组,如果需要更新一个数组的话,必须需要把数组解出来
 let [getArr, setArr] = useState([]);
 //这边定义一个数组
 let arr = [1,2,3]
 //正确更新方式
 setArr(...arr)
 //错误方式setArr(arr)

5.amap map style update

Regarding the switching of map styles, using amap.setMapStyle (style) does not require re-calling the map method. Although re-calling the map can also switch the map, it will flash for a while, which is very unfriendly.

//使用amap.setMapStyle()
const G4 = {
     default: "amap://styles/*****************",
     dark: "amap://styles/*****************",
 };
let mapStyle = G4.default;
//这样切换就不需要重新调用地图方法了,而且重新调用地图虽然也能切换地图但是会闪一下,及其不友好
amap.setMapStyle(mapStyle);

6. Map custom icon window offset problem

pit! : Then there is the problem of map point offset when refreshing, and when clicking outside the map to display points, the layout is disordered or offset. 

At this time, you only need to go to the browser f12 to inspect the code, find the css style of amap , and add absolute positioning to the style to solve the problem. If it does not take effect at the current node, write absolute positioning to the previous node, such as mine, this It should be a must. Remove the border, customize the border, remove the inner margin, and then adjust it through left and top . In this way, even if you click to add a new point when it is displayed outside the map, it will not be affected by display:none , and the style will be lost. Caused by display:none . Because if your points on the map are not within the visible range of your screen, those point elements belong to a state of display:none . Display:none does not occupy space. When display:none is directly on the demo node, Deleted, so it will cause a problem of losing a style

So, it is best to add the following code to solve the problem. Of course, there may be other better methods.

.amap-marker-label {
  padding: 0;
  border: none;
  background-color: unset;
  position: absolute;
  left: -150px !important;
  top: -15px !important;
}

There is also the problem of icon offset, which can be easily solved.

as code

//这个是一个自定义的图标,amap地图,点位的自定义图片
function cameraCard(src = iconA) {
  const vnode = (
    <div className="imgBox">
      <img className="mapicon" src={src} alt="" />
    </div>
  );
  return vnode;
}

If refreshed or the data changes, the icon will appear offset.

So just add absolute positioning to the css of imgBox to solve the problem.

.imgBox {
  position: absolute;
}

7. Map transform and position: fixed conflict issues

Then inside the map, it is not recommended to use position: fixed ; because amap uses a lot of transforms , and transform conflicts with position: fixed , and will downgrade position: fixed to absolute , which cannot achieve the effect of window positioning! So it’s better to put the html that needs position: fixed  outside the map.

The above codes are all typed by hand. If there are any errors, please point them out.

Guess you like

Origin blog.csdn.net/xiaoxiongxia/article/details/132019415