UNPKG

@uiw/react-amap-map

Version:

基于 React 封装的高德地图组件。AMap Component Based On React.

378 lines (321 loc) 17.9 kB
<div markdown="1"> <sup>使用 <a href="https://wangchujiang.com/#/app" target="_blank">我的应用</a> 也是一种 <a href="https://wangchujiang.com/#/sponsor" target="_blank">支持</a> 我的方式:</sup> <br> <a target="_blank" href="https://apps.apple.com/app/Vidwall/6747587746" title="Vidwall for macOS"><img align="center" alt="Vidwall" height="52" width="52" src="https://github.com/user-attachments/assets/7b5df70a-ed91-4d4b-85be-f00e60a09ce9"></a> <a target="_blank" href="https://wangchujiang.com/mousio-hint/" title="Mousio Hint for macOS"><img align="center" alt="Mousio Hint" height="52" width="52" src="https://github.com/user-attachments/assets/3c0af128-0cef-44e5-a8db-4741dc5a6690"></a> <a target="_blank" href="https://apps.apple.com/app/6746747327" title="Mousio for macOS"><img align="center" alt="Mousio" height="52" width="52" src="https://github.com/user-attachments/assets/9edf61ff-5a6c-4676-9cc2-8fd3c1ad0dfb"></a> <a target="_blank" href="https://apps.apple.com/app/6745227444" title="Musicer for macOS"><img align="center" alt="Musicer" height="52" width="52" src="https://github.com/user-attachments/assets/b7abfba8-88ff-4c86-a125-43073d5aef22"></a> <a target="_blank" href="https://apps.apple.com/app/6743841447" title="Audioer for macOS"><img align="center" alt="Audioer" height="52" width="52" src="https://github.com/user-attachments/assets/7a836865-8c90-4119-87bc-19e06a76c957"></a> <a target="_blank" href="https://apps.apple.com/app/6744690194" title="FileSentinel for macOS"><img align="center" alt="FileSentinel" height="52" width="52" src="https://github.com/user-attachments/assets/28bce2cc-290e-45bf-9068-585ff6ecafe9"></a> <a target="_blank" href="https://apps.apple.com/app/6743495172" title="FocusCursor for macOS"><img align="center" alt="FocusCursor" height="52" width="52" src="https://github.com/user-attachments/assets/d543668a-737b-4853-a6bb-eaa269e69836"></a> <a target="_blank" href="https://apps.apple.com/app/6742680573" title="Videoer for macOS"><img align="center" alt="Videoer" height="52" width="52" src="https://github.com/user-attachments/assets/10ffb0f1-0625-40d6-93f1-2c2496592595"></a> <a target="_blank" href="https://apps.apple.com/app/6740425504" title="KeyClicker for macOS"><img align="center" alt="KeyClicker" height="52" width="52" src="https://github.com/user-attachments/assets/5a19fcb9-cb81-4855-b4ea-31c604d9612a"></a> <a target="_blank" href="https://apps.apple.com/app/6739052447" title="DayBar for macOS"><img align="center" alt="DayBar" height="52" width="52" src="https://github.com/user-attachments/assets/771b608d-594c-492d-8532-d9231e383f5b"></a> <a target="_blank" href="https://apps.apple.com/app/6739444407" title="Iconed for macOS"><img align="center" alt="Iconed" height="52" width="52" src="https://github.com/user-attachments/assets/8a35dc7b-4faf-4e2a-9311-f66d6844a896"></a> <a target="_blank" href="https://apps.apple.com/app/6737160756" title="RightMenu Master for macOS"><img align="center" alt="RightMenu Master" height="52" width="52" src="https://github.com/user-attachments/assets/39a76541-71bf-4de7-a01c-c62f0557dff5"></a> <a target="_blank" href="https://apps.apple.com/app/6723903021" title="Paste Quick for macOS"><img align="center" alt="Quick RSS" height="52" width="52" src="https://github.com/user-attachments/assets/bdaad5b7-9810-44ce-8f17-8410864465d2"></a> <a target="_blank" href="https://apps.apple.com/app/6670696072" title="Quick RSS for macOS/iOS"><img align="center" alt="Quick RSS" height="52" width="52" src="https://github.com/user-attachments/assets/374106b5-a448-4d1d-9ccb-b04b6bc681ed"></a> <a target="_blank" href="https://apps.apple.com/app/6670167443" title="Web Serve for macOS"><img align="center" alt="Web Serve" height="52" width="52" src="https://github.com/user-attachments/assets/e1d9f76f-0f3d-4ba5-8a15-253ee173bb1c"></a> <a target="_blank" href="https://apps.apple.com/app/6503953628" title="Copybook Generator for macOS/iOS"><img align="center" alt="Copybook Generator" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/b90e42ff-158b-4534-82ca-5898fd0e8d73"></a> <a target="_blank" href="https://apps.apple.com/app/6471227008" title="DevTutor for macOS/iOS"><img align="center" alt="DevTutor for SwiftUI" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/f15c154d-0192-48eb-8e0e-9e245ffd974a"></a> <a target="_blank" href="https://apps.apple.com/app/6479819388" title="RegexMate for macOS/iOS"><img align="center" alt="RegexMate" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/aabe5aa9-9a96-4390-8bed-c3e4023d0dea"></a> <a target="_blank" href="https://apps.apple.com/app/6479194014" title="Time Passage for macOS/iOS"><img align="center" alt="Time Passage" height="52" width="52" src="https://github.com/jaywcjlove/time-passage/assets/1680273/6f30e429-e6f3-4dbe-9921-a5effe2a05e9"></a> <a target="_blank" href="https://apps.apple.com/app/6478772538" title="IconizeFolder for macOS"><img align="center" alt="Iconize Folder" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/fa9d8b9c-1e51-4ded-877c-fa5b21c47220"></a> <a target="_blank" href="https://apps.apple.com/app/6478511402" title="Textsound Saver for macOS/iOS"><img align="center" alt="Textsound Saver" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/0595e842-980b-4574-8891-a8ba853a08be"></a> <a target="_blank" href="https://apps.apple.com/app/6476924627" title="Create Custom Symbols for macOS"><img align="center" alt="Create Custom Symbols" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/8cd022ce-a3f1-4e89-b7c6-6fbd0d4db77c"></a> <a target="_blank" href="https://apps.apple.com/app/6476452351" title="DevHub for macOS"><img align="center" alt="DevHub" height="52" width="52" src="https://github.com/user-attachments/assets/4a44a4fd-67ce-430b-af0a-72f18feaa47d"></a> <a target="_blank" href="https://apps.apple.com/app/6476400184" title="Resume Revise for macOS"><img align="center" alt="Resume Revise" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/c9954a20-1905-48de-bdf8-d71837974aa2"></a> <a target="_blank" href="https://apps.apple.com/app/6472593276" title="Palette Genius for macOS"><img align="center" alt="Palette Genius" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/27340413-d355-45b2-8f6f-6ac37682d957"></a> <a target="_blank" href="https://apps.apple.com/app/6470879005" title="Symbol Scribe for macOS"><img align="center" alt="Symbol Scribe" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/c7249f05-fa70-4def-a1e9-571d5f171fc9"></a> </div> <hr> Map 组件 === [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) [![npm version](https://img.shields.io/npm/v/@uiw/react-amap-map.svg)](https://www.npmjs.com/package/@uiw/react-amap-map) [![Downloads](https://img.shields.io/npm/dm/@uiw/react-amap-map.svg?style=flat)](https://www.npmjs.com/package/@uiw/react-amap-map) Map 组件是其他组件的基础,Map 组件会通过 Context 给所有的子组件提供 **`map`**,**`container`** 和 **`AMap`**,对象。 ⚠️ 注意 > 1. 组件 `<Map>` 必须包裹在 `<APILoader>` 组件内,该组件作用是加载高德地图 SDK。 > 2. 其他地图组件必须作为 `<Map>` 的子组件使用; > 3. 在 ~~v2.5.0+~~ -> v5 通过 props 传递 **`map`**,**`container`** 和 **`AMap`** 对象,在 v6 版本中移除了,通过 Context 传递对象 ```jsx import { Map, APILoader } from '@uiw/react-amap'; // 或者单独安装使用 import { Map } from '@uiw/react-amap-map'; ``` ### 基本用法 Map 的父组件必须具有宽度和高度; ```jsx mdx:preview import React from 'react'; import ReactDOM from 'react-dom'; import { Map, APILoader } from '@uiw/react-amap'; const Demo = () => ( <div style={{ width: '100%', height: '300px' }}> <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Map /> </APILoader> </div> ); export default Demo ``` ### useMapContext 通过 React 的 Context 提供了一个`无需`为每层组件手动注入 ~~`map`~~,~~`container`~~ 和 ~~`AMap`~~ 三个属性 `props`,就能在组件树间进行传递。 ```jsx mdx:preview import React, { useRef, useEffect } from 'react'; import ReactDOM from 'react-dom'; import { useMap, useMapContext, APILoader, Provider } from '@uiw/react-amap'; const Marker = () => { const warpper = useRef(null); const { map, state } = useMapContext(); const { setContainer } = useMap({ container: warpper.current, center: [116.397428, 39.90923], zoom: 10 }); useEffect(() => { if (map) { const marker = new AMap.Marker({ icon: new AMap.Icon({ imageSize: new AMap.Size(25, 34), image: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png' }), position: [116.405285,39.904989], offset: new AMap.Pixel(-13, -30) }); // 创建点标记 const marker1 = new AMap.Marker({ position: new AMap.LngLat(116.32945,39.939772) }); map.add(marker1); marker.setMap(state.map); } }, [map]); useEffect(() => { if (warpper.current) { setContainer(warpper.current); } }, [warpper.current]); return <div ref={warpper} style={{ height: 300 }} />; } const Demo = () => ( <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Provider> <Marker /> </Provider> </APILoader> ); export default Demo ``` ```jsx import { useMapContext, Provider } from '@uiw/react-amap'; const { AMaps, map, container, state, dispatch } = useMapContext(); // => state.AMaps // => state.map // => state.container ``` ### 参数设置 ```jsx mdx:preview import ReactDOM from 'react-dom'; import React, { Fragment, useState } from 'react'; import { Map, APILoader } from '@uiw/react-amap'; function Demo() { const [dragEnable, setDragEnable] = useState(true); const [display, setDisplay] = useState(true); const [zoom, setZoom] = useState(15); const [center, setCenter] = useState([116.397428, 39.90923]); const [viewMode, setViewMode] = useState('3D'); return ( <Fragment> <button onClick={() => setDragEnable(!dragEnable)}>{dragEnable ? '禁用' : '启用'}拖拽</button> <button onClick={() => setDisplay(!display)}>{display ? '卸载' : '加载'}地图</button> <button onClick={() => setViewMode(viewMode === '3D' ? '2D' : '3D')}>{viewMode}地图</button> <button onClick={() => setZoom(zoom + 1)}>放大 +1 -> ({zoom})</button> <button onClick={() => setZoom(zoom - 1)}>缩小 -1 -> ({zoom})</button> <button onClick={() => setZoom(zoom - 1)}>缩小 -1 -> ({zoom})</button> <button onClick={() => setCenter([121.394147,31.262488])}>上海</button> <button onClick={() => setCenter([116.397428, 39.90923])}>北京</button> <div style={{ width: '100%', height: 350 }}> {display && ( <Map dragEnable={dragEnable} zoom={zoom} center={center} viewMode={viewMode} pitch={viewMode === '2D' ? 0 : 70} /> )} </div> </Fragment> ); } const Mount = () => ( <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Demo /> </APILoader> ); export default Mount; ``` ### Ref 获取地图实例对象。 ```jsx mdx:preview import ReactDOM from 'react-dom'; import React, { useEffect, useRef, Fragment } from 'react'; import { Map, APILoader } from '@uiw/react-amap'; function Demo() { const mapRef = useRef(); useEffect(() => { console.log('mapRef:', mapRef) }, []); return ( <div style={{ width: '100%', height: 130 }}> <Map layers={[new AMap.TileLayer.Satellite()]} ref={(instance) => { if (instance && instance.map) { const bounds = instance.map.getBounds(); console.log('instance', instance); } }} /> <Map layers={[new AMap.TileLayer.Satellite()]} ref={mapRef} /> </div> ); } const Mount = () => ( <div style={{ width: '100%', height: '300px' }}> <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Demo /> </APILoader> </div> ); export default Mount; ``` ### 事件触发 ```jsx mdx:preview import ReactDOM from 'react-dom'; import React from 'react'; import { Map, APILoader } from '@uiw/react-amap'; const Demo = () => ( <div style={{ width: '100%', height: '300px' }}> <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Map onComplete={(data, de) => { console.log('地图加载完成!', data, de); }} onClick={() => { console.log('点击事件!'); }} /> </APILoader> </div> ); export default Demo ``` ### 特殊使用方法 通过 `Map` 的子组件函数,返回三个对象 **`map`**,**`container`** 和 **`AMap`**, ```jsx mdx:preview import ReactDOM from 'react-dom'; import React, { useEffect, useRef, Fragment } from 'react'; import { Map, APILoader, ScaleControl, ToolBarControl, ControlBarControl, Geolocation } from '@uiw/react-amap'; const Demo = () => ( <div style={{ width: '100%', height: '300px' }}> <Map center={[116.397428, 39.90923]} zoom={12}> {({ AMap, map, container }) => { console.log('map', map) if (map) { const marker = new AMap.Marker({ icon: new AMap.Icon({ imageSize: new AMap.Size(25, 34), image: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png' }), position: [116.405285,39.904989], offset: new AMap.Pixel(-13, -30) }); marker.setMap(map); } return; }} </Map> </div> ); const Mount = () => ( <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Demo /> </APILoader> ); export default Mount; ``` ### 将子组件封装到一个组件中 ```jsx mdx:preview import ReactDOM from 'react-dom'; import React, { useState, useRef } from 'react'; import { Map, APILoader, Polyline, ToolBarControl } from '@uiw/react-amap'; const path1 = [ [121.099109,31.222311], [118.528308,31.989555], [117.319812,31.803006], [114.353503,30.67583], [115.891589,28.979429], [112.947253,28.188361], ]; const path2 = [ [116.405289, 39.904987], [113.964458, 40.54664], [111.47836, 41.135964], [108.949297, 41.670904], [106.380111, 42.149509], [103.774185, 42.56996], [101.135432, 42.930601], [98.46826, 43.229964], [95.777529, 43.466798], [93.068486, 43.64009], [90.34669, 43.749086], [87.61792, 43.793308], ]; const ChildComp = (props = {}) => { return ( <div> <Polyline {...props} visiable={true} strokeOpacity={1} path={path1} /> <Polyline {...props} visiable={true} strokeOpacity={1} path={path2} /> </div> ) } const Demo = () => { const [show, setShow] = useState(true); return ( <div style={{ width: '100%', height: '300px' }}> <Map zoom={3}> {(props) => { return <ChildComp {...props} />; }} </Map> </div> ); } const Mount = () => ( <APILoader akey="a7a90e05a37d3f6bf76d4a9032fc9129"> <Demo /> </APILoader> ); export default Mount; ``` ### Props [更多参数设置](https://github.com/uiwjs/react-amap/blob/268303d/src/types/core.d.ts#L461-L537) | 参数 | 说明 | 类型 | 默认值 | |--------- |-------- |--------- |-------- | | container | (**默认不需要传递**) 构造一个地图对象,参数 container 中传入地图容器 DIV 对象。<br />注意:地图容器在创建之前必须拥有实际大小,否则可能出现底图无法渲染的问题。 | `HTMLDivElement` | - | | center | 初始中心经纬度 | `[number, number] \| LngLat` | - | ### 事件 [事件类型文档](https://github.com/uiwjs/react-amap/blob/268303d/src/types/core.d.ts#L298-L403) | 参数 | 说明 | 类型 | | ---- | ---- | ---- | | onComplete | 地图资源加载完成后触发事件 | - | | onMouseMove | 鼠标在地图上移动时触发 | - | | onZoomChange | 地图缩放级别更改后触发 | - | | onMapMove | 地图平移时触发事件 | - | | onMouseWheel | 鼠标滚轮开始缩放地图时触发 | - | | onZoomStart | 缩放开始时触发 | - | | onMouseOver | 鼠标移入地图容器内时触发 | - | | onMouseOut | 鼠标移出地图容器时触发 | - | | onDblClick | 鼠标左键双击事件 | - | | onClick | 鼠标左键单击事件 | - | | onZoomEnd | 缩放结束时触发 | - | | onMoveEnd | 地图移动结束后触发,包括平移,以及中心点变化的缩放。如地图有拖拽缓动效果,则在缓动结束后触发 | - | | onMouseUp | 鼠标在地图上单击抬起时触发 | - | | onMouseDown | 鼠标在地图上单击按下时触发 | - | | onRightClick | 鼠标右键单击事件 | - | | onMoveStart | 地图平移开始时触发 | - | | onDragStart | 开始拖拽地图时触发 | - | | onDragging | 拖拽地图过程中触发 | - | | onDragEnd | 停止拖拽地图时触发。如地图有拖拽缓动效果,则在拽停止,缓动开始前触发 | - | | onHotspotOut | 鼠标移出热点时触发 | - | | onHotspotOver | 鼠标滑过热点时触发 | - | | onTouchStart | 触摸开始时触发事件,仅适用移动设备 | - | | onHotspotClick | 鼠标点击热点时触发 | - | | onTouchMove | 拖拽地图过程中触发,仅适用移动设备 | - | | onTouchEnd | 触摸结束时触发事件,仅适用移动设备 | - | | onResize | 地图容器尺寸改变事件 | - |