React+高德地圖實時獲取經緯度,定位地址

1.根據高德官方的教程進行前期的配置 高德地圖JSAPI 1.4.15文檔
2.參照官方示例中心完成地圖的創建 示例中心

接下來,首先看效果圖:

1. 初始化地圖

地圖容器創建後,初始化時需要配置一些默認的參數,這裡配置瞭常用的幾個,其他的效果自己可以參考api去添加

Dom:<div id='map_container'>
        //地圖容器
    </div>
    
//定義一個地圖類
class GeoMap {
    constructor() {
        this.el = 'map_container'
        this.defaultConfig = { //默認配置
            zoom: 16,              // 默認縮放級別
            touchZoomCenter: 1,    // 為1時縮放以地圖中心
            resizeEnable: true,    // 監控地圖容器尺寸變化
            doubleClickZoom: true, // 雙擊放大地圖
        }
        this.map = null   // 地圖實例
        this.mapMove = false // 地圖是否移動中
        this.centerPixel = { y: '-999', x: '-999' } // 紮點默認位置
    }
    // 初始化地圖
    initFn() {
        this.createMap()
        // ...
    }
    // 創建實例
    createMap() {
        this.map = new AMap.Map(this.el, this.defaultConfig)
        // 給地圖添加自己喜歡的風格(背景顏色)
        this.map.setMapStyle('amap://styles/28d5c5df182464d14316bfa41383096c')
    }
    // ...
 }
 export default new GeoMap()

2. 地圖紮點

首先實現在地圖上繪制一個中心點,需要實現的效果:

  1. 不能隨著地圖的拖動而移動
  2. 在地圖容器的中心位置

地圖盒子作為父元素,紮點進行絕對定位,實現瞭第一點;

    Dom: <div id='map_container'> //地圖容器
          <div id='center_icon' style={{left: `${實例.centerPixel.x}px`, top: `${實例.centerPixel.y}px` }}>
            <img src='紮點圖片' /> // 文章結尾有紮點動畫介紹
          </div>
       </div>
    css: #map_container {
            flex: 1;
            position: relative;
            #center_icon {
                position: absolute;
                z-index: 101;
                >img{  
                    width: 52px;
                    height: 64px;
                    // --------以下代碼下面會做詳細介紹---------
                    position: relative;
                    top: -64px;
                    left: -26px;
                }
            }
         }

然後需要設置紮點的left和top值,如何動態的紮點的像素值呢? 這裡我們通過高德api, getCenter()獲取地圖中心經緯度坐標 lngLatToContainer() 地圖經緯度坐標轉為地圖容器像素坐標

    setCenterIcon() {
        let lnglat = this.map.getCenter()
        let pixel = this.map.lngLatToContainer(lnglat)
        this.centerPixel = pixel
    }

紮點圖片需要相對定位自身高度top:-自身高度 left:-自身寬度/2,原因是:定位點是以盒子的左上角定位到中心的(虛線盒子),所以我們需要將(虛線盒子)移動到(實線盒子)位置,這樣紮點的位置就準確瞭。請看下圖:

3. 開啟定位

需要實現:

  • 進入地圖頁面自動開啟定位功能
  • 定位成功後的位置作為地圖的中心點

這兩個都是通過api實現,比較簡單;定位失敗後返回中文提示

    getLocation() {
        const mapError = new Map([
            ['Get ipLocation failed.', 'IP精確定位失敗'],
            ['Browser not Support html5 geolocation.', '瀏覽器不支持原生定位接口'],
            ['Geolocation permission denied.', '瀏覽器禁止瞭非安全域的定位請求'],
            ['Get geolocation time out.', '瀏覽器定位超時'],
            ['Get geolocation failed.', '定位失敗']
        ])
        this.map.plugin('AMap.Geolocation', () => {
            const geolocation = new AMap.Geolocation({
                enableHighAccuracy: true, //是否使用高精度定位
                timeout: 30000,           //超過n秒後停止定位
                showButton: false,        //顯示定位按鈕
                showMarker: true,         //定位成功後在定位到的位置顯示點標記
                showCircle: false,        //定位成功後用圓圈表示定位精度范圍
                panToLocation: true,      //定位成功後將定位到的位置作為地圖中心點---
                zoomToAccuracy: true,     //調整地圖視野范圍使定位位置及精度范圍視野內可見
            })
            this.map.setZoom(16) // 縮放比例改變後重新定位時設置初始縮放比例
            this.map.addControl(geolocation)  // 添加控件
            geolocation.getCurrentPosition()  // 進入頁面時自動定位
            AMap.event.addListener(geolocation, 'complete', (result) => {
                // 不在這裡取數據,因為返回的經緯度、詳細地址偏差比較大----下面有獲取精確地址的介紹
            })
            AMap.event.addListener(geolocation, 'error', (err) => { // 定位失敗的錯誤提示
                let msg = mapError.get(err.message) || err.message
                console.log(msg);
            })
        })
    }

4. 監聽地圖變化

通過api調用實現監聽地圖變化:移動中、移動結束、縮放、拖拽等

    mapMove() {
        // * 地圖移動中
        this.map.on('mapmove', () => {
           this.mapMove = false
        })
        // * 地圖移動結束
        this.map.on('moveend', () => {
            this.mapMove = true
            this.getCenterAddress() // 獲取地址----下面會做詳細介紹
        })
    }

5. 獲取詳細地址

在地圖移動結束後,通過API去獲取詳細地址。首先說下這兩個API:

  1. AMap.PlaceSearch().searchNearBy() 根據中心點經緯度、半徑以及關鍵字進行周邊查詢
  2. AMap.Geocoder().getAddress() 地理編碼與逆地理編碼服務,用於地址描述與坐標間的相互轉換

🤔按理來說感覺第二種返回比第一種要精確,但是經過多次試驗,第一種反而更精確;可以將兩種方式做個兼容,這裡隻舉例第一種

    getCenterAddress() {
        let lnglat = this.map.getCenter()
        AMap.service('AMap.PlaceSearch', () => {
            let placeSearch = new AMap.PlaceSearch({
                    pageSize: 10,
                    pageIndex: 1,
                    children: 1,
                    extensions: 'all',
                    type: '通行設施|地名地址信息|政府機構及社會團體|樓宇|產業園區|風景名勝|機場出發/到達|火車站|港口碼頭|長途汽車站|地鐵站|輕軌站|公交車站',
                })
            let center = [lnglat.lng, lnglat.lat]
            placeSearch.searchNearBy('', center, 50, (sta, result) => {
                if (sta === 'complete' && result.info === 'OK') {
                    // result.poiList.pois 數組第一項就是獲取的精確地址
                })
            })
    }

6. 紮點動畫😄

在地圖移動結束後給紮點添加一個上下跳動的動畫,移動時取消動畫

    Dom: <img src='紮點圖片' className={實例.mapMove ? 'pinAnima' : ''}/>
    
    css: 
        .pinAnima{
            animation: bounce 0.75s;
        }
        
    @keyframes bounce {
    0% {
        transform: translateY(0)
    }
    50% {
        transform: translateY(-20px);
    }
    100% {
        transform: translateY(0)
    }
}

7. 結束

思路其實沒有那麼復雜,把地圖想成一個盒子容器,地圖中心點想成盒子中心點;紮點在【地圖中心點】不會動,當移動地圖時,去獲取【地圖中心點】經緯度,設置某個位置的時候,將經緯度設置為【地圖中心點】即可。

還有一些其他功能,比如:推薦位置設置、繪制路線、路徑規劃、汽車行駛、雷達動畫、等 感興趣的可以一起研究下。在手機定位也會有一些定位失敗,定位超時等的問題,也可以一起研究下。

以上就是React+高德地圖實時獲取經緯度,定位地址的詳細內容,更多關於React 定位地址的資料請關註WalkonNet其它相關文章!

推薦閱讀: