coleava / me

1 stars 0 forks source link

react接入高德地图手册及部分问题记录 #46

Open coleava opened 1 year ago

coleava commented 1 year ago

v1.4 地图JS API: https://lbs.amap.com/api/javascript-api/summary v2.0 地图JS API:https://lbs.amap.com/api/jsapi-v2/guide/overlays/marker

本篇以v2.0开展

JS API 2.0 版本提供了两种方案引入地图 JSAPI:

  1. 使用官网提供的 JSAPI Loader 进行加载;
  2. 以常规 JavaScript 脚本的方式加载; 注意:为避免地图数据协议和前端资源不匹配导致页面运行报错,只允许在线加载 JSAPI,禁止进行本地转存、与其它代码混合打包等用法。

使用 JSAPI Loader (推荐) JSAPI Loader是我们提供的 API 加载器,可帮助开发者快速定位、有效避免加载引用地图 JSAPI 各种错误用法,具有以下特性:

按普通 JS 方式使用 Loader

<script src="https://webapi.amap.com/loader.js"></script>
<script type="text/javascript" >
AMapLoader.load({
    "key": "",              // 申请好的Web端开发者Key,首次调用 load 时必填
    "version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    "plugins": [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
    "AMapUI": {             // 是否加载 AMapUI,缺省不加载
        "version": '1.1',   // AMapUI 版本
        "plugins":['overlay/SimpleMarker'],       // 需要加载的 AMapUI ui插件
    },
    "Loca":{                // 是否加载 Loca, 缺省不加载
        "version": '2.0'  // Loca 版本
    },
}).then((AMap)=>{
        var map = new AMap.Map('container');
        map.addControl(new AMap.Scale());
    }).catch((e)=>{
        console.error(e);  //加载错误提示
    });   
</script>
``
_**注意(您在2021年12月02日申请以后的key需要配合您的安全密钥一起使用)**_

- JSAPI key和安全密钥的使用
   方式一: 
    1. JSAPI key搭配代理服务器并携带安全密钥转发(安全)
        引入地图 JSAPI 脚本之前增加代理服务器设置脚本标签,设置代理服务器域名或地址,将下面示例代码中的「您的代理服务器域名或地址」替换为您的代理服务器域名或ip地址,其中_AMapService为代理请求固定前缀,不可省略或修改。(注意您这个设置必须是在  JSAPI 的脚本加载之前进行设置,否则设置无效。)
  <script type="text/javascript">
    window._AMapSecurityConfig = {
        serviceHost:'您的代理服务器域名或地址/_AMapService',  
        // 例如 :serviceHost:'http://1.1.1.1:80/_AMapService',
    }
  </script>
  <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=您申请的key值"></script> 

``

  1. 代理服务器的设置 以 Nginx 反向代理为例,参考以下三个location配置,进行反向代理设置,分别对应自定义地图、海外地图、Web服务,其中自定义地图和海外地图如果没有使用到相关功能也可以不设置。需要将以下配置中的“您的安全密钥”六个字替换为您刚刚获取的jscode安全密钥。如果您使用了多个key,需要在代理设置中根据 key来映射不同的安全密钥
server {
        listen       80;             #nginx端口设置,可按实际端口修改
        server_name  127.0.0.1;      #nginx server_name 对应进行配置,可按实际添加或修改

        # 自定义地图服务代理
        location /_AMapService/v4/map/styles {
            set $args "$args&jscode=您的安全密钥";
            proxy_pass https://webapi.amap.com/v4/map/styles;
        }
        # 海外地图服务代理
        location /_AMapService/v3/vectormap {
            set $args "$args&jscode=您的安全密钥";
            proxy_pass https://fmap01.amap.com/v3/vectormap;
        }
        # Web服务API 代理
        location /_AMapService/ {
            set $args "$args&jscode=您的安全密钥";
            proxy_pass https://restapi.amap.com/;
        }
}

保存相关配置之后需要通过命令nginx -s reload 命令重新加载 nginx 配置文件

方式二(不建议): JSAPI key搭配静态安全密钥以明文设置(不安全,建议开发环境用):

引入地图 JSAPI 脚本之前增加设置 JSAPI 安全密钥的脚本标签,并将您的安全密钥「您申请的安全密钥」替换为您的安全密钥;(注意这个设置必须是在 JSAPI 的脚本加载之前进行设置,否则设置无效。)

<script type="text/javascript">
        window._AMapSecurityConfig = {
            securityJsCode:'您申请的安全密钥',
        }
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=您申请的key值"></script> 

React示例代码

import React from 'react'
import './MapContainer.css'
import AMapLoader from '@amap/amap-jsapi-loader'
import { Input, List } from 'antd'

class MapComponent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [],
    }
    this.map = {}
    this.AMap = null
    this.markerList = []
  }
  // 2.dom渲染成功后进行map对象的创建
  componentDidMount() {
    AMapLoader.load({
      key: 'xxxxxx', // 申请好的Web端开发者Key,首次调用 load 时必填
      version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
      plugins: ['AMap.HeatMap'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
    })
      .then((AMap) => {
        this.AMap = AMap
        this.map = new AMap.Map('container', {
          //设置地图容器id
          // viewMode:"3D",         //是否为3D地图模式
          zoom: 12,
          //   center: [116.397428, 39.90923],
          center: [121.38054, 31.22593], //初始化地图中心点位置
          //   rotation: 60,
          terrain: true,
        })
      })
      .catch((e) => {
        console.log(e)
      })
  }

  search = (keyword) => {
    this.map.plugin(['AMap.AutoComplete'], () => {
      var autoOptions = {
        //city 限定城市,默认全国
        city: '上海',
      }
      // 实例化AutoComplete
      var autoComplete = new this.AMap.AutoComplete(autoOptions)
      // 根据关键字进行搜索
      console.log('autoComplete', autoComplete)
      autoComplete.search(keyword, (status, result) => {
        // 搜索成功时,result即是对应的匹配数据\
        let { tips } = result
        this.setState({ list: tips || [] }, () => {
          let markerList = []
          this.state.list.map((tip) => {
            let marker = new this.AMap.Marker({
              position: new this.AMap.LngLat(tip.location.lng, tip.location.lat), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
              title: tip.name,
              icon: 'https://webapi.amap.com/theme/v1.3/markers/b/mark_bs.png',
            })
            marker.on('click', (e) => {
              console.log('ee', e)
              let { list } = this.state
              let ls = []
              ls = list.filter((x) => {
                if (x.name == e.target._opts.title) {
                  x['border'] = '1px solid red'
                  x['padding'] = 8
                } else {
                  x['border'] = ''
                  x['padding'] = 0
                }
                return x
              })
              this.setState({ list: ls })
            })
            markerList.push(marker)
          })
          this.markerList = markerList
          this.map.add(markerList)
          if (this.state.list.length > 0) {
            this.map.setZoomAndCenter(14, [this.state.list[0].location.lng, this.state.list[0].location.lat], false, 1500)
          }
        })
      })
    })
  }

  select = (item) => {
    this.markerList.map((marker) => {
      if (marker._opts.title == item.name) {
        marker.setIcon('https://vdata.amap.com/icons/b18/1/2.png')
      } else {
        marker.setIcon('https://webapi.amap.com/theme/v1.3/markers/b/mark_bs.png')
      }
      return marker
    })
  }
  render() {
    // 1.初始化创建地图容器,div标签作为地图容器,同时为该div指定id属性;
    return (
      <div style={{ overflowY: 'hidden', height: '100vh' }}>
        <div id="container" className="map" style={{ height: '60vh' }}></div>
        <Input.Search className="map-input" onSearch={(val) => this.search(val)} />

        <List
          style={{ margin: '0 16px', overflowY: 'auto' }}
          itemLayout="horizontal"
          dataSource={this.state.list}
          renderItem={(item) => (
            <List.Item
              style={{ cursor: 'pointer', border: item.border || '', padding: item.padding || 0 }}
              onClick={() => {
                this.select(item)
              }}>
              <List.Item.Meta title={<a>{item.name}</a>} description={item.address} />
            </List.Item>
          )}
        />
      </div>
    )
  }
}
//导出地图组建类
export default MapComponent

问题

  1. 高德地图查询接口 返回的结果为 USER_DAILY_QUERY_OVER_LIMIT ,则表示查询次数超出次数 image

  2. 高德地图查询接口 返回的结果为INVALID_USER_SCODE 安全秘钥未填写而导致的错误 代码中key和安全密码要同时使用 image

zhangdianxu commented 5 months ago

谷歌浏览器-高德地图定位失败geolocation time out,怎么解决