谷歌地图amap使用教程,详细版,react,vue通用

我的框架 vite + react ,其实vue也一样差不多

一.前置工作

先去官网去申请个key,地址:高德开放平台 | 高德地图API

先登录然后进入控制台

 然后打开应用管理,我的应用

 然后创建新应用

 新建完成后,创建key

 然后

提交完成,就可以拿到key了,如果一开始需要认证就认证一下 

二.安装amap

可以npm 或者 yarn 安装

npm install @amap/amap-jsapi-loader

然后正式开始编写代码咯

三.引入amap组件和使用(react版本)

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;

三.删除点位和新增点位

如果需要隐藏或者删除点位的话,使用 amap.remove(需要删除的数组)

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

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

如果存在多个数组点位增删改查的的话也很好解决

同理

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] = [];
    }
  
} 


 

四.react数组更新注意事项

如果是react的话需要用到useState()钩子函数,然后就是useState()使用中需要注意的东西,比如

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

五.amap地图样式更新

关于地图的样式的切换,使用amap.setMapStyle(样式)这样切换就不需要重新调用地图方法了,而且重新调用地图虽然也能切换地图但是会闪一下,及其不友好

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

六.地图自定义图标窗口偏移问题

坑!:然后还有刷新出现地图点位偏移的一个问题,以及在地图外点击显示点位,出现布局错乱或者是偏移的问题 

这个时候只需要去浏览器f12 巡查一下代码,找到amap的css样式,给样式加上个绝对定位即可解决问题,如果在当前节点不生效进行往上一个节点写绝对定位,如我这个,这个应该是必加的,去除边框自定义边框,去除内边距,然后通过lefttop调整,这样的话即使在地图外显示点击新增点位,也不会给display:none影响到,样式丢失也是display:none导致的。因为地图你的点位不在你屏幕的可视范围内的话,那些点位元素是属于一个display:none的一个状态,display:none的是不占用空间的,当display:none在demo节点上面是直接删除的,所以会导致一个样式丢失的一个问题

so,以下代码最好还是加上,就把问题解决了,当然可能也有更好其他方法

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

还有一个是图标偏移问题,这个就很好解决了,

如代码

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

如果刷新,或者数据变动的话的这个图标就会出现一个偏移

所以直接给imgBox这个css加上绝对定位即可解决

.imgBox {
  position: absolute;
}

七.地图transform和position: fixed冲突问题

然后就是在地图内部,不建议使用position: fixed;因为amap使用了大量的transform,而transform是和position: fixed冲突的,会把position: fixed 降级为absolute,达不到窗口定位的一个效果!所以还是把需要用到position: fixed 用的html 放在地图外边

以上代码皆为手敲,如有错误,望能指出

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值