react使用高德地图react-amap:Map、Markers、Circle、ContextMenu、自定义ContextMenu

本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/240316

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的