本文主要是介绍react使用高德地图react-amap:Map、Markers、Circle、ContextMenu、自定义ContextMenu,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
React AMap — 基于 React 的高德地图组件
目录
搜索区域代码
地图区域代码
自定义菜单样式
复杂而且不好口述,直接上代码,后面出视频
搜索区域代码
// ------------------外部资源
import React, { useEffect } from 'react'
import { observer } from 'mobx-react-lite'
import { Form, Button, Input, Select } from 'antd'
const { Option } = Select
// ------------------内部公共
import SearchSelect from "react-antd-search-select";// ------------------内部私有
import store from '../../store'export default observer(() => {const [form] = Form.useForm()const onEmployeeChange = () => {form.setFieldsValue({ customerId: undefined })store.setStore({ customerId: '' })onSearchParamsChange()}// 搜索客户const onSearchParamsChange = () => {const data = form.getFieldsValue(true)data.area = undefineddata.range = undefinedif (data.employeeId) {store.setStore({ employeeId: data.employeeId })store.getCustomerLocationList(data)} else {store.setStore({employeeId: '',customerId: '',visitInfo: {},customerLocationList: []})}}// 客户const onCustomerChange = (value) => {store.setStore({ customerId: value })}// 重置const handleClear = () => {const employeeId = form.getFieldsValue(true).employeeIdform.resetFields()form.setFieldsValue({ employeeId })store.setStore({ customerId: null, range: undefined, area: '' })employeeId && store.getCustomerLocationList({ employeeId })}useEffect(() => {if (store.useInfo?.isSale) {form.setFieldsValue({employeeId: store.useInfo?.employeeId})store.getCustomerLocationList({ employeeId: store.useInfo?.employeeId })}}, [store.useInfo])useEffect(() => {form.setFieldsValue({ range: store.range, area: store.area })}, [store.range, store.area])return (<><div className="search-block"><Formlayout="inline"form={form}><Form.Item label="销售" name="employeeId"><SearchSelecturl="/api/selectEmployee"width={200}onChange={onEmployeeChange}/></Form.Item><Form.Item label="合作状态" name="customerSignType"><Select placeholder="请选择" allowClear onChange={onSearchParamsChange} style={{ width: 100 }}><Option value={0}>未合作</Option><Option value={1}>合作中</Option><Option value={2}>合作结束</Option></Select></Form.Item><Form.Item label="客户" name="customerId"><SearchSelectvalue={store.customerId}width={200}url="/customermap/search-customer.json"ajaxData={{initCondition: 'Init_LptCustomer',queryField: 'name',queryType: 'select_customer',isNeedPerssion: true,extendCondition: JSON.stringify([{"queryField":"creatorId","queryOption":"=","queryValue": store.employeeId}])}}onChange={onCustomerChange}/></Form.Item><Form.Item name="area"><Input placeholder="区域/地点" allowClearonChange={(e) => store.setStore({ area: e.target.value })} /></Form.Item><Form.Item name="range"><Select placeholder="周边" allowClear style={{ width: 100 }}onChange={(value) => store.setStore({ range: value })}><Option value={1}>1公里以内</Option><Option value={2}>2公里以内</Option><Option value={3}>3公里以内</Option><Option value={4}>4公里以内</Option><Option value={5}>5公里以内</Option></Select></Form.Item><Form.Item><Button onClick={handleClear}>清除</Button></Form.Item></Form></div><style jsx>{`.search-block {padding: 10px 20px;}`}</style></>)
})
地图区域代码
// ------------------外部资源
import React, { useState, useEffect, useRef } from 'react';
import { observer } from 'mobx-react-lite'
import { toJS } from "mobx";
import {Modal, Spin } from 'antd';
import { Map, Markers, Circle } from 'react-amap';
import { useDebounceFn } from "ahooks";
// ------------------内部公共
import EditVisitPlan from "@components/EditVisitPlan";
import mark_gray from '@static/images/mark_gray.png'
import mark_green from '@static/images/mark_green.png'
// ------------------内部私有
import store from '../../store'
import './index.less'
let currentMarkerData = {}
let markerMap = []
let MapsOption = {}// 自定义菜单
const CustomContextMenu = ({ coverLocations, mapsOption, showRange, addVisit, setCurrentMarkerData }) => {return (<ul className="custom-amap-menu"style={{left: mapsOption.pixel.x + 5,top: mapsOption.pixel.y}}>{coverLocations.map(item => {const row = JSON.parse(item)return <li key={row.customerId}><span>{row.customerName}</span><ul className="customer-menus"><li onClick={() => {setCurrentMarkerData?.(row)showRange?.()}}>显示周边范围</li><li onClick={() => {setCurrentMarkerData?.(row)addVisit?.()}}>增加拜访计划</li><li><a href={`/customer/todetail/?customerId=${row.customerId}&isinfoEdit=1`} target="_blank">重新维护地址</a></li><li><a href={`/customervisitplan/listall/?customer_id=${row.customerId}`} target="_blank">查看拜访记录</a></li><li><a href={`/customer/todetail/?customerId=${row.customerId}`} target="_blank">查看客户详情</a></li></ul></li>})}</ul>)
}export default observer(() => {const mapInstance = useRef(null); // created map 记录map实例instanceconst contextMenu = useRef(null); // 菜单const [zoom, setZoom] = useState(11) // 缩放const [coordinates, setCoordinates] = useState([]) // 当前坐标点const [radius, setRadius] = useState(0) // 半径范围rangeconst [markers, setMarkers] = useState([]) // Markers 数据const [visible, setVisible] = useState(false) // Circle 显示const [editVisitPlanVisible, setEditVisitPlanVisible] = useState(false) // 增加拜访计划显示const [customContextMenuVisible, setCustomContextMenuVisible] = useState(false) // 自定义菜单显示// 监听客户位置列表变化,控制地图显示useEffect(() => {getMarkers()store?.visitInfo?.city && debounceSetAddrLocation.run(store?.visitInfo?.city)}, [store.customerLocationList])// 监听客户变化useEffect(() => {if (markers.length && (store.customerId || store.customerId === 0)) {const customer = markers.find(item => {return item?.extData?.customerId === Number(store.customerId)})console.log('customer', customer);if (customer) {setZoom(16)setCoordinates(customer.position)store.setStore({ range: 3, customer })setVisible(true)setIconRed(customer, 500)} else {store.setStore({ customer: {} })Modal.warning({content: (<div>当前所选客户还没有坐标,<a href={`/customer/todetail/?customerId=${store.customerId}&isinfoEdit=1`} target="_blank">现在去维护</a></div>),okText: '取消'});}} else {setZoom(11)setCoordinates([116.397428, 39.90923])store.setStore({ range: undefined, customer: {} })setVisible(false)}}, [store.customerId])// 标红点const setIconRed = (customer, timeout) => {if (!Object.keys(store.customer).length) returnsetTimeout(() => {// 标红for(const item of markerMap) {if (customer?.extData?.isCover) {if (item?.w?.extData?.position.join() === customer?.position?.join()) {item.render(() => {return <img src='//webapi.amap.com/theme/v1.3/markers/n/mark_r.png' />})}} else {if (item?.w?.extData?.extData.customerId === customer?.extData?.customerId) {item.render(() => {return <img src='//webapi.amap.com/theme/v1.3/markers/n/mark_r.png' />})}}}}, timeout)}// 监听区域、地点变化,获取对应经纬点useEffect(() => {store?.area && debounceSetAddrLocation.run(store?.area);}, [store.area])// 监听周边变化,设置Circle⭕️半径useEffect(() => {setRadius(store.range * 1000)}, [store.range])// 监听经纬坐标、区域变化,控制Circle⭕️显示useEffect(() => {if (coordinates && store.area) {setZoom(16);setVisible(true)} else {setVisible(false)}}, [store.area])// 获取地图 Markersconst getMarkers = () => {const list = []for(const item of toJS(store.customerLocationList)) {const position = item.location?.split(',')if (position.length === 2) {list.push({position,extData: item})}}setMarkers(list)store.setStore({ area: '' })store.setStore({ range: undefined })}// render动态修改标记的外观iconconst renderMarkerFn = (extData) => {let icon = '//webapi.amap.com/theme/v1.3/markers/n/mark_bs.png'if (extData?.extData?.visitPlanStatus === 1) {icon = mark_gray} else if (extData?.extData?.visitPlanStatus === 2) {icon = mark_green}return <img src={icon} />};// 根据城市名做地理/逆地理编码 获取经纬坐标const setAddrLocation = (area) => {window.AMap.plugin('AMap.Geocoder', () => {let geocoder = new window.AMap.Geocoder({// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycodecity: store?.visitInfo?.city});// 使用geocoder做地理/逆地理编码geocoder.getLocation(area, (status, result) => {if (status === 'complete' && result.info === 'OK') {const location = result.geocodes[0].location;setCoordinates([location.lng, location.lat])if (store.area && result.info === 'OK') store.setStore({ range: 3 })}});});};const debounceSetAddrLocation = useDebounceFn(setAddrLocation);// 显示周边范围const showRange = () => {setZoom(16);setCoordinates(currentMarkerData.location.split(','));store.setStore({ range: 3, customerId: currentMarkerData.customerId })setVisible(true)}// 增加拜访计划const addVisit = () => {setEditVisitPlanVisible(true)}// Markers 事件const events = {created: (markers) => {for (const item of markers) {markerMap.push(item)}},click: (mapsOption, marker) => {currentMarkerData = marker.getExtData().extDatasetCustomContextMenuVisible(false)if (currentMarkerData.isCover === 1) {const customAmapMenu = document.getElementsByClassName('custom-amap-menu')if (customAmapMenu.length === 0) {MapsOption = mapsOptionsetCustomContextMenuVisible(true)}} else {contextMenu.current.open(mapInstance.current, mapsOption.lnglat);}},mouseover: (mapsOption, marker) => {marker.setLabel({offset: new window.AMap.Pixel(20, 20), // 修改label相对于maker的位置content: marker.w.extData.extData.showName})marker.setTop(true);},mouseout: (mapsOption, marker) => {marker.setLabel({content: null});marker.setTop(false);}}// 地图事件const mapEvents = {created: (instance) => {mapInstance.current = instance;contextMenu.current = new window.AMap.ContextMenu();contextMenu.current.addItem("显示周边范围", showRange, 0);contextMenu.current.addItem("增加拜访计划", addVisit, 1);contextMenu.current.addItem("重新维护地址", function() {window.open(`/customer/todetail/?customerId=${currentMarkerData.customerId}&isinfoEdit=1`);}, 2);contextMenu.current.addItem("查看拜访记录", function() {window.open(`/customervisitplan/listall/?customer_id=${currentMarkerData.customerId}`);}, 3);contextMenu.current.addItem("查看客户详情", function() {window.open(`/customer/todetail/?customerId=${currentMarkerData.customerId}`);}, 4);},click: () => setCustomContextMenuVisible(false),mapmove: () => setCustomContextMenuVisible(false),zoomchange: () => {const list = [...markers]console.log('mapInstance.current.getZoom()', mapInstance.current.getZoom());setZoom(mapInstance.current.getZoom());if (mapInstance.current.getZoom() > 12) {for(const item of list) {item.label = {content: item.extData.showName,offset: new window.AMap.Pixel(20, 20)}}} else {for(const item of list) {item.label = undefined}}setMarkers(list)console.log('keys', );setIconRed(store.customer)setCustomContextMenuVisible(false)},};return (<Spin spinning={store.loading} ><div id="customer-maps" style={{width: '100%', height: 'calc(100vh - 184px)'}}><div style={{ display: store.customerLocationList.length ? 'block' : 'none', height: '100%', width: '100%' }}><Mapamapkey="0fe0e92d23dc183b6384d51515676b81"version="1.4.0"plugins={['Scale', 'ToolBar']}center={coordinates}isHotspot={true}zoom={zoom}events={mapEvents}><Markersmarkers={markers}events={events}render={renderMarkerFn}/><Circlecenter={ coordinates }radius={ radius }visible={ visible }style={{strokeColor: "#F33", // 线颜色strokeOpacity: 1, // 线透明度strokeWeight: 3, // 线粗细度fillColor: "#ee2200", // 填充颜色fillOpacity: 0.15 // 填充透明度}}draggable={ false }bubble/></Map></div>{/* 增加拜访计划 */}{editVisitPlanVisible &&<EditVisitPlanvisible={editVisitPlanVisible}params={{customerId: currentMarkerData.customerId,customerName: currentMarkerData.customerName,title: '增加拜访计划',isEdit: false,isPhone: true,onSave: () => setEditVisitPlanVisible(false),onCancel: () => setEditVisitPlanVisible(false)}}/>}{/* 重复坐标点的自定义菜单 */}{customContextMenuVisible &&<CustomContextMenumapsOption={MapsOption}coverLocations={ currentMarkerData.coverLocations }showRange={showRange}addVisit={addVisit}setCurrentMarkerData={(data) => currentMarkerData = data}/>}</div></Spin>)
})
自定义菜单样式
#customer-maps {position: relative;.custom-amap-menu {position: absolute;top: 100px;left: 300px;border: 1px solid #ccc;background: #fff;z-index: 111;padding: 0;ul, li {padding: 0;margin: 0;list-style:none}li {height: 30px;line-height: 30px;padding: 0 10px;position: relative;}li:hover {background: #eee;}li:hover ul {display: block;}ul {width: 100px;position: absolute;top: 0;right: -100px;display: none;background: #fff;border: 1px solid #ccc;z-index: 111;}ul li {height: 30px;line-height: 30px;padding: 0 10px;text-align: center;cursor: pointer;}ul li:hover {background: #eee;}a {color: #5f6d80;}a:hover {text-decoration: none;}ul li a {display: block;}}
}
这篇关于react使用高德地图react-amap:Map、Markers、Circle、ContextMenu、自定义ContextMenu的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!