react-amap海量点优化

前言:高版本的react-amap 支持MassMarkers 组件用于一次性添加大量的标记点。本次优化的海量点是在低版本react-amap的基础上。官方推荐使用聚合useCluster属性来优化海量点的渲染。

直接附上代码:

import React, { Component } from "react";
import { Map, Markers, Polygon, InfoWindow } from 'react-amap'
import {Form,Switch,message,
} from "antd";
import ActionsForm from "components/RoutePanel/ActionsForm";
import { MAP_AMAP_KEY, MAP_AMAP_VERSION } from 'constants/config'
import {API_FETCH_ZONES_DEPT_POINT,
} from 'constants/api'
import fetch from 'common/fetch'
import styles from "./amap.css";
import { debounce } from 'lodash';const polygonType = {main: 'main',adjacent: 'adjacent',normal: 'normal',
}// 获取区域样式
const getPolygonStyle = (pt) => {switch (pt) {case polygonType.main: return {fillColor: '#DC2626',fillOpacity: 0.5,strokeOpacity: 0.5,strokeWeight: 2,strokeColor: '#DC2626',}case polygonType.adjacent:return {fillColor: '#34D399',fillOpacity: 0.5,strokeOpacity: 1,strokeWeight: 1,strokeColor: '#34D399',}case polygonType.normal:default:return {fillColor: '#333333',fillOpacity: 0.3,strokeOpacity: 0.5,strokeWeight: 1,strokeColor: '#333333',}}
}export class ZoneNeighborhoodMap extends Component {constructor(props) {super(props)this.map = null; // 地图实例this.mapEvents = {created: (mapInstance) => {this.map = mapInstance;this.map.on('zoomend', this.handleZoom);},close: () => {this.map = null;if (this.map) {this.map.off('zoomend', this.handleZoom);}}};this.state = {infoWindowPosition: null,infoWindowTitle: '',polygonActive: false,pointReferShow: true, //运输点参考pointReferData: [],areaReferShow: true, //已绘制参考areaReferData: [],locTypes: [],data: props.data,// infoWindowPosition: {//   longitude: 120,//   latitude: 30,// },infoWindowVisible: false,infoWindowData: {id: "",desc: "",},infoWindow: {position: {longitude: 120,latitude: 30,},visible: false,data: null,},useCluster:false}this.markerEvents = {created: (e) => {},mouseover: (e) => {const position = e.target.getPosition();this.setState({infoWindow: {position: {longitude: position.lng,latitude: position.lat,},visible: true,data: e.target.getExtData(),},});},mouseout: (e) => {this.setState({infoWindow: {position: {longitude: 120,latitude: 30,},visible: false,data: null,},});},};}componentWillUnmount() {if (this.map) {this.map.destroy();}}componentWillUnmount() {if (this.map) {this.map.destroy()}}// 缩放事件处理函数handleZoom = () => {const zoomLevel = this.map.getZoom();console.log('zoomLevel',zoomLevel)if (zoomLevel > 8) {this.setState({ useCluster: false });} else {this.setState({ useCluster: true });}};setFitViewWithZoneId(zoneId) {const fitOverlays = []this.map.getAllOverlays().forEach(polygon => {if (polygon.getExtData().zoneId === zoneId) {fitOverlays.push(polygon)}})if (fitOverlays.length) {this.map.setFitView(fitOverlays, false, undefined, this.map.getZoom())}}renderPolygons() {const { mainZoneId, polygons, toggleAdjacentZone, adjacentZoneIds } = this.propsconst l = polygons.lengthconst _polygons = []for (let i = 0; i < l; i++) {const detail = polygons[i]if (detail.geoArea && detail.geoArea.length) {let _polygonType = polygonType.normalif (detail.zoneId === mainZoneId) {_polygonType = polygonType.main} else if (adjacentZoneIds.includes(detail.zoneId)) {_polygonType = polygonType.adjacent}detail.geoArea.forEach((path, pathId) => {_polygons.push(<Polygon path={path}key={`${detail.id}:${pathId}`}style={getPolygonStyle(_polygonType)}events={{click: () => {if (detail.zoneId === mainZoneId) {return}toggleAdjacentZone(detail.zoneId)},mousemove: (e) => {this.setState(() => ({infoWindowPosition: e.lnglat,infoWindowTitle: detail.zoneDesc}))},mouseout: () => {this.setState(() => ({infoWindowPosition: null}))}}}extData={{ zoneId: detail.zoneId }}/>)})}}return _polygons}renderInfoWindow() {const { infoWindowPosition, infoWindowTitle } = this.stateif (!infoWindowPosition) {return null}return <InfoWindowposition={{longitude: infoWindowPosition.lng,latitude: infoWindowPosition.lat,}}isCustom={true}content={`<div style="pointer-events: none;background: #fff;border:1px solid silver;padding: 4px 8px;">${infoWindowTitle}</div>`}offset={[2,-10]}visible/>}getPoint = ()=>{fetch(API_FETCH_ZONES_DEPT_POINT, {method: 'POST',headers: {'Accept': 'application/json','Content-Type': 'application/json'},body: JSON.stringify({ deptId:this.props.deptId })}).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if(json.data instanceof Array){if (!json.data.length) {message.info("没有可显示的运输地点");}else{if(json.data.length > 500){this.setState({useCluster: true,})}json.data.forEach(d=>d.position= { longitude: d.longitude, latitude: d.latitude })this.setState({pointReferData:json.data},()=>{if (!this.map) return; // 如果地图实例未初始化,则不执行this.map.setFitView();})}}}).catch(e=>{})}renderInfo = () => {const { position, visible, data } = this.state.infoWindow;const {locTypes} = this.stateif (!data) {return null;}const locTypeItem = locTypes.find(t=>t.domVal==data.locType)const tds = (<div  className={styles.info}><div className='inforow'><span>运输地点代码</span><span>{data.locId}</span></div><div className='inforow'><span>运输地点描述</span><span>{data.locDesc}</span></div><div className='inforow'><span>类型</span><span>{locTypeItem?locTypeItem.domValDesc:data.locType}</span></div><div className='inforow'><span>城市</span><span>{data.city}</span></div><div className='inforow'><span>省份</span><span>{data.province}</span></div><div className='inforow'><span>国家</span><span>{data.country}</span></div><div className='inforow'><span>经度</span><span>{data.longitude}</span></div><div className='inforow'><span>纬度</span><span>{data.latitude}</span></div><div className='inforow'><span>地址</span><span>{data.addr}</span></div><div className='inforow'><span>限行区域</span><span>{data.udzDesc1}({data.udz1})</span></div><div className='inforow'><span>业务区域</span><span>{data.udzDesc2}({data.udz2})</span></div></div>);return (<InfoWindowposition={position}visible={visible}isCustom={true}offset={[2, 2]}>{tds}</InfoWindow>);};pointRender = (extData) => {return (<divstyle={{color: "#4e72b8",width: "8px",height: "8px",borderRadius: "50%",background: "#4169E1",textAlign: "center",}}/>);};initPointReferData = () => {if (!this.state.pointReferShow) {this.setState({pointReferData: [],});} else {this.getPoint()}};componentDidMount() {this.initPointReferData();}// 运输点参考// changePointReferShow = (checked) => {//   this.setState({ pointReferShow: checked }, () => {//     this.initPointReferData();//   });// };changePointReferShow = debounce((checked) => {this.setState({ pointReferShow: checked }, () => {this.initPointReferData();});}, 300); // 300ms 的防抖延迟render() {const {polygonActive,pointReferShow,data,pointReferData,areaReferData,areaReferShow,} = this.state;const option = {amapkey: MAP_AMAP_KEY,version: MAP_AMAP_VERSION,mapStyle: 'amap://styles/whitesmoke',// loading: this.renderLoading(),status: {resizeEnable: true,},plugins: ['ToolBar', 'Scale'],events: this.mapEvents,}return (<div style={{ width: "100%", height: "100vh", position: "relative" }}><ActionsForm><Form layout="inline"><Form.Item><SwitchcheckedChildren="显示地点"unCheckedChildren="显示地点"checked={pointReferShow}onChange={this.changePointReferShow}/></Form.Item></Form></ActionsForm><Map {...option}><Markersmarkers={pointReferData}offset={[0,0]}render={this.pointRender}events={this.markerEvents}useCluster={this.state.useCluster}/>{this.renderPolygons()}{this.renderInfoWindow()}{this.renderInfo()}</Map></div>);}
}

希望点的数量少于1000时直接展示所有点,不聚合

import React, { Component } from "react";
import PropTypes from "prop-types";
import Immutable from 'seamless-immutable';
import {Map,Polygon,Markers,PolyEditor,MouseTool,InfoWindow,
} from "react-amap";
import {Form,Button,Switch,Tooltip,Modal,message,Menu,Dropdown,Popconfirm,Icon,
} from "antd";
import isomorphicFetch from "isomorphic-fetch";
import {API_FETCH_DOMAIN,API_FETCH_ZONES_DEPT_POINT,API_FETCH_ZONES_GROUP
} from 'constants/api'
import fetch from 'common/fetch'import {MAP_AMAP_KEY,MAP_AMAP_DRIVING_KEY,MAP_AMAP_VERSION,
} from "constants/config";
import ActionsForm from "components/RoutePanel/ActionsForm";
import ZoneCascader from "components/PcaCascader/ZoneCascader";
import pstyles from "./polygons.scss";// 获取封闭polygon(首尾点坐标一致)
const _getClosedPolygon = (paths) => {if (Array.isArray(paths) && paths.length > 2) {const firstLocation = paths[0];const lastLocation = paths[paths.length - 1];if (firstLocation[0] === lastLocation[0] &&firstLocation[1] === lastLocation[1]) {return paths;} else {return [...paths, firstLocation];}} else {return [];}
};class PolygonEdit extends Component {constructor(props) {super(props);this.state = {polygonActive: false,pointReferShow: true, //运输点参考pointReferData: [],areaReferShow: false, //已绘制参考areaReferData: [],locTypes: [],data: props.data,mapEditable: props.mapEditable,deleteMenuVisible: false,hoverItemData: [],adcode: "",province: "",provinceCode:"",city: "",cityCode:"",area: "",street: "",polyline: "",infoWindowPosition: {longitude: 120,latitude: 30,},infoWindowVisible: false,infoWindowData: {id: "",desc: "",},infoWindow: {position: {longitude: 120,latitude: 30,},visible: false,data: null,},showLabels: true, // 默认显示悬浮名称useCluster:false};const _this = this;this.amap = null; // 地图this.mouseTool = null; // 鼠标工具this.amapEvents = {created: (mapInstance) => {_this.amap = mapInstance;_this.amap.on('zoomend', this.handleZoom);},close: () => {_this.amap = null;if (_this.amap) {_this.amap.off('zoomend', this.handleZoom);}},};this.polyEditorEvents = {created: (ins) => {_this.amap.setFitView();},addnode: () => {},adjust: ({ lnglat, pixel, type, target } = option) => {},removenode: () => {},end: ({ type, target }) => {this.polyEditorEnd(target, type);},};this.polygonEvents = {created: (ins) => {_this.amap.setFitView();},};this.toolEvents = {created: (tool) => {_this.mouseTool = tool;},draw({ obj }) {_this.drawWhat(obj);},};this.markerEvents = {created: (e) => {},mouseover: (e) => {const position = e.target.getPosition();this.setState({infoWindow: {position: {longitude: position.lng,latitude: position.lat,},visible: true,data: e.target.getExtData(),},});},mouseout: (e) => {this.setState({infoWindow: {position: {longitude: 120,latitude: 30,},visible: false,data: null,},});},};}componentWillUnmount() {if (this.amap) {this.amap.destroy();}}componentDidMount() {if(this.props.isGroup){this.initPointReferData();this.initAreaReferData()}this.getLocType()}// 缩放事件处理函数handleZoom = () => {const zoomLevel = this.amap.getZoom();console.log('zoomLevel', zoomLevel);console.log('this.state.pointReferData.length', this.state.pointReferData.length);// 判断点的数量是否小于1000,以及当前缩放等级if (this.state.pointReferData.length > 1000 && zoomLevel < 10) {this.setState({ useCluster: true });} else {this.setState({ useCluster: false });}};getPoint = ()=>{fetch(API_FETCH_ZONES_DEPT_POINT, {method: 'POST',headers: {'Accept': 'application/json','Content-Type': 'application/json'},body: JSON.stringify({ deptId:this.props.deptId })}).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if(json.data instanceof Array){if (!json.data.length) {message.info("没有可显示的运输地点");}else{json.data.forEach(d=>d.position= { longitude: d.longitude, latitude: d.latitude })this.setState({pointReferData:json.data},()=>{if (!this.amap) return; // 如果地图实例未初始化,则不执行this.amap.setFitView();})}}}).catch(e=>{})}renderPolygons = () => {const { areaReferShow, areaReferData } = this.state;const GROUP_KEY = {unConfiguredGroups: 'unConfiguredGroups',configuredGroups: 'configuredGroups'}const prepareGroups = (groups) => {const _groups = Immutable.asMutable(groups, { deep: true }).map(group => ({...group,zoneDetail: (group.zoneDetail || []).map(detail => {return {...detail,geoArea: JSON.parse(detail.geoArea)}})}))return {groups,[GROUP_KEY.unConfiguredGroups]: _groups.filter(group => !group.lines.length).map(group => ({...group,lines: []})),[GROUP_KEY.configuredGroups]: _groups.filter(group => group.lines.length),zoneOptions: _groups.map(group => ({value: group.zoneId,label: group.zoneDesc,})),polygons: _groups.reduce((polygons, group) => {polygons.push(...group.zoneDetail.map(zoneDetail => ({ ...zoneDetail, zoneDesc: group.zoneDesc }))) // flat zoneDetailreturn polygons}, [])}}const newData = prepareGroups(areaReferData)const polygons = newData.polygonsconst l = polygons.lengthconst _polygons = []for (let i = 0; i < l; i++) {const detail = polygons[i]if (detail.geoArea && Array.isArray(detail.geoArea) && detail.geoArea.length) {detail.geoArea.forEach((path, pathId) => {_polygons.push(<Polygon path={path}key={`${detail.id}:${pathId}`}style={{fillColor: '#333333',fillOpacity: 0.3,strokeOpacity: 0.5,strokeWeight: 1,strokeColor: '#333333',}}events={{mousemove: (e) => {this.setState(() => ({infoWindowPosition: e.lnglat,infoWindowTitle: detail.zoneDesc}))},mouseout: () => {this.setState(() => ({infoWindowPosition: null}))}}}extData={{ zoneId: detail.zoneId }}/>)})}else{console.log('detail.geoArea',detail.geoArea)}}return _polygons}getArea = ()=>{fetch(API_FETCH_ZONES_GROUP, {method: 'POST',credentials: 'include',headers: {'Accept': 'application/json','Content-Type': 'application/json'},body: JSON.stringify({ branchId:this.props.branchId,deptId:this.props.deptId})}).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if(json.data && json.data.data instanceof Array){if (!json.data.data.length) {message.info("没有可显示的区域");}else{this.setState({areaReferData:json.data.data})}}}).catch(e=>{console.log('e',e)})}renderInfoWindow() {const { infoWindowPosition, infoWindowTitle, showLabels } = this.stateif(showLabels){if (!infoWindowPosition) {return null}return <InfoWindowposition={{longitude: infoWindowPosition.lng,latitude: infoWindowPosition.lat,}}isCustom={true}content={`<div style="pointer-events: none;background: #fff;border:1px solid silver;padding: 4px 8px;">${infoWindowTitle}</div>`}offset={[2,2]}visible/>}}initPointReferData = () => {if (!this.state.pointReferShow) {this.setState({pointReferData: [],});} else {this.getPoint()}};initAreaReferData = () => {if (!this.state.areaReferShow) {this.setState({areaReferData: [],});} else {this.getArea()}};renderLoading = () => {const loadingStyle = {position: "relative",height: "100%",width: "100%",display: "flex",justifyContent: "center",alignItems: "center",};return <div style={loadingStyle}>Loading Map...</div>;};// 运输点参考changePointReferShow = (checked) => {this.setState({ pointReferShow: checked }, () => {this.initPointReferData();});};// 已绘制区域参考changeAreaReferShow = (checked) => {this.setState({ areaReferShow: checked }, () => {this.initAreaReferData();});};// 是否悬浮显示名称toggleLabels = (checked) => {this.setState({ showLabels: checked });};pointRender = (extData) => {return (<divstyle={{color: "#4e72b8",width: "8px",height: "8px",borderRadius: "50%",background: "#4169E1",textAlign: "center",}}/>);};getLocType=()=>{fetch(`${API_FETCH_DOMAIN}LOCATION_TYPE`,{credentials: 'include'}).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if(json.data instanceof Array){this.setState({locTypes:json.data})}}).catch(e=>{})}renderInfo = () => {const { position, visible, data } = this.state.infoWindow;const {locTypes} = this.stateif (!data) {return null;}const locTypeItem = locTypes.find(t=>t.domVal==data.locType)const tds = (<div  className={pstyles.pinfo}><div className='inforow'><span>运输地点代码</span><span>{data.locId}</span></div><div className='inforow'><span>运输地点描述</span><span>{data.locDesc}</span></div><div className='inforow'><span>类型</span><span>{locTypeItem?locTypeItem.domValDesc:data.locType}</span></div><div className='inforow'><span>城市</span><span>{data.city}</span></div><div className='inforow'><span>省份</span><span>{data.province}</span></div><div className='inforow'><span>国家</span><span>{data.country}</span></div><div className='inforow'><span>经度</span><span>{data.longitude}</span></div><div className='inforow'><span>纬度</span><span>{data.latitude}</span></div><div className='inforow'><span>地址</span><span>{data.addr}</span></div><div className='inforow'><span>限行区域</span><span>{data.udzDesc1}({data.udz1})</span></div><div className='inforow'><span>业务区域</span><span>{data.udzDesc2}({data.udz2})</span></div></div>);return (<InfoWindowposition={position}visible={visible}isCustom={true}offset={[2, 2]}>{tds}</InfoWindow>);};// polygon edit switchtogglePolygon = (checked, e) => {if (checked) {// open edit and close add if it is drawingif (this.mouseTool) {this.mouseTool.close();}this.setState({ polygonActive: true, isDrawingPolygon: false });} else {// close editthis.setState({ polygonActive: false });}};// polygon add switchtoggleDrawPolygon = (checked, e) => {if (checked) {if (this.mouseTool) {this.mouseTool.polygon();this.setState({ isDrawingPolygon: true });message.success("鼠标左键双击或右键单击完成当前多边形!");}} else {if (this.mouseTool) {this.mouseTool.close();this.setState({ isDrawingPolygon: false });}}};// finish polygon drawdrawWhat = (obj) => {const paths = obj.getPath();let data = this.state.data.slice();const pathData = paths.map((item) => [item.lng, item.lat]);if (pathData.length > 2) {if (this.amap) {this.amap.remove(obj);}data.push(_getClosedPolygon(pathData));this.setState({ data });message.success(`您成功绘制了一个${paths.length}边形,可继续绘制或点击结束多边形绘制按钮`);}};// polygon editor endpolyEditorEnd = (target, type) => {const paths = target.getPath();let isSinglePath = false; // 是否是单围栏const pathData = paths.map((item, index) => {if (Array.isArray(item)) {const itemPaths = item.map((element) => [element.lng, element.lat]);return _getClosedPolygon(itemPaths);} else {isSinglePath = true;return [item.lng, item.lat];}});this.setState({data: isSinglePath ? [_getClosedPolygon(pathData)] : pathData,});};// 多边形删除下拉菜单deleteMenuVisibleChange = (flag) => {this.setState({ deleteMenuVisible: flag });};// 删除多边形handleMenuClick = (e) => {this.handleDeletePath(e.key);};handleDeletePath = (key) => {const path = [...this.state.data];path.splice(key, 1);this.setState({ data: path, deleteMenuVisible: false });};handleMenuHover = (key) => {this.setState({ hoverItemData: this.state.data[key] });};handleChangeAdcode = ({ adcode, province, city, area, street,provinceCode,cityCode }) => {this.setState({ adcode, province, city, area, street,provinceCode, cityCode});};handleAdcodeCancle = () => {this.setState({adcode: "",province: "",provinceCode:"",city: "",cityCode:"",area: "",street: "",});};handleAdcodeConfirm = () => {const { adcode, provinceCode, cityCode, area, street, mapEditable } = this.state;if (adcode) {this.setState({mapEditable: "N",adcode: "",polygonActive: false,isDrawingPolygon: false,});if (street) {isomorphicFetch(`/city-tiles/${provinceCode}_${cityCode}.json`).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if (json.status === "0") {throw new Error("No districts from server");}try {const streetItemData = json.features.find((s) => s.properties.subdistrict == street).geometry.coordinates;if (this.mouseTool) {this.mouseTool.close();}this.setState({data: streetItemData, // some data});if (this.amap) {this.amap.setFitView();}} catch (e) {message.error("获取行政区划数据失败!");}// const polyline = (json.districts && json.districts[0]) ? json.districts[0].polyline : [];// const data = polyline.split('|').map(block => block.split(';').map(pointer => pointer.split(',').map(lnglat => Number(lnglat))));// if (this.mouseTool){//   this.mouseTool.close();// }// this.setState({//   data: data, // some data// })// if (this.amap) {//   this.amap.setFitView();// }}).catch((error) => {message.error("获取行政区划数据失败!");this.setState({mapEditable: "Y",province: "",provinceCode:"",city: "",cityCode:"",area: "",street: "",data: [],});});} else {// fetch polyline dataisomorphicFetch(`//restapi.amap.com/v3/config/district?key=e17fafe279209e4b3a303cc907347277&keywords=${adcode}&subdistrict=0&extensions=all`).then((response) => {if (response.ok) {return response.json();}throw new Error("Bad response from server");}).then((json) => {if (json.status === "0") {throw new Error("No districts from server");}const polyline =json.districts && json.districts[0]? json.districts[0].polyline: [];const data = polyline.split("|").map((block) =>block.split(";").map((pointer) =>pointer.split(",").map((lnglat) => Number(lnglat))));if (this.mouseTool) {this.mouseTool.close();}this.setState({data: data, // some data});if (this.amap) {this.amap.setFitView();}}).catch((error) => {message.error("获取行政区划数据失败!");this.setState({mapEditable: "Y",province: "",provinceCode:"",city: "",cityCode:"",area: "",street: "",data: [],});});}} else {if (mapEditable === "N") {this.setState({mapEditable: "Y",adcode: "",province: "",provinceCode:"",city: "",cityCode:"",area: "",street: "",data: [],});}}};handleFinished = () => {const {polygonActive,data,adcode,province,city,area,street,mapEditable,} = this.state;let result = {geoArea:Array.isArray(data) && data.length > 0 ? JSON.stringify(data) : null,mapEditable,};if (mapEditable === "N") {Object.assign(result, {country: "中国",state: province,city,district: area,subdistrict: street,});}if (polygonActive) {this.setState({ polygonActive: false });Modal.confirm({title: "您的多边形调整还未结束,是否结束?",onOk: () => {this.props.onConfirm(result);},onCancel: () => {this.setState({ polygonActive: true });},});} else {this.props.onConfirm(result);}};render() {const {polygonActive,isDrawingPolygon,pointReferShow,data,pointReferData,areaReferData,areaReferShow,deleteMenuVisible,hoverItemData,adcode,mapEditable,infoWindowPosition,infoWindowVisible,infoWindowData,showLabels,useCluster} = this.state;const { onCancle, isGroup } = this.props;const option = {amapkey: MAP_AMAP_KEY,version: MAP_AMAP_VERSION,mapStyle: "amap://styles/whitesmoke",loading: this.renderLoading(),status: {resizeEnable: true,},plugins: ["ToolBar", "Scale"],events: this.amapEvents,};return (<div style={{ width: "100%", height: "100vh", position: "relative" }}><ActionsForm>{isGroup ? (<Form layout="inline"><Form.Item><Popconfirmtitle={<ZoneCascaderadcode={adcode}onChange={this.handleChangeAdcode}/>}icon={<Tooltip title="选择行政区划。此操作将首先清空已有围栏,已选择的行政区划围栏不允许编辑"><Icon type="question-circle-o" /></Tooltip>}onCancel={this.handleAdcodeCancle}onConfirm={this.handleAdcodeConfirm}><Button type="primary">行政区划选择{isGroup}</Button></Popconfirm></Form.Item><Form.Item><Switchdisabled={mapEditable === "N"}checkedChildren="调整"unCheckedChildren="调整"checked={polygonActive}onChange={this.togglePolygon}/></Form.Item><Form.Item><Switchdisabled={mapEditable === "N"}checkedChildren="新增"unCheckedChildren="新增"checked={isDrawingPolygon}onChange={this.toggleDrawPolygon}/></Form.Item><Form.Item><Dropdownoverlay={<Menu onClick={this.handleMenuClick}>{data &&data.length > 0 &&data.map((item, index) => (<Menu.Item key={index}><spanonMouseOver={() => this.handleMenuHover(index)}>{`${index + 1} 删除`}</span></Menu.Item>))}</Menu>}onVisibleChange={this.deleteMenuVisibleChange}visible={deleteMenuVisible}disabled={mapEditable === "N"}><Button>删除</Button></Dropdown></Form.Item><Form.Item><Button onClick={onCancle}>取消</Button></Form.Item><Form.Item><Button type="primary" onClick={this.handleFinished}>完成</Button></Form.Item><Form.Item><SwitchcheckedChildren="显示地点"unCheckedChildren="显示地点"checked={pointReferShow}onChange={this.changePointReferShow}/></Form.Item><Form.Item><SwitchcheckedChildren="显示其他区域"unCheckedChildren="显示其他区域"checked={areaReferShow}onChange={this.changeAreaReferShow}/></Form.Item><Form.Item><SwitchcheckedChildren="显示区域名称"unCheckedChildren="隐藏区域名称"checked={showLabels}onChange={this.toggleLabels}/></Form.Item></Form>) : (<Form layout="inline"><Form.Item><Button type="primary" onClick={onCancle}>关闭</Button></Form.Item></Form>)}</ActionsForm><Map {...option}><Markersmarkers={pointReferData}offset={[0,0]}render={this.pointRender}events={this.markerEvents}useCluster={useCluster}/>{isGroup && <MouseTool events={this.toolEvents} />}{isGroup ? (<Polygonpath={data}style={{ fillOpacity: 0.3, strokeOpacity: 0.5, strokeWeight: 1 }}events={this.polygonEvents}><PolyEditoractive={polygonActive && data.length > 0 && data.flat().length <= 100}events={this.polyEditorEvents}/></Polygon>) : (data.map((item, index) => (<Polygonevents={this.polygonEvents}key={index}path={item}style={{fillOpacity: 0.3,strokeOpacity: 0.5,strokeWeight: 1,}}/>)))}<Polygonvisible={deleteMenuVisible}path={[hoverItemData]}zIndex={100}style={{fillColor: "red",fillOpacity: 0.3,strokeOpacity: 0.5,strokeWeight: 1,}}/>{this.renderInfo()}{this.renderPolygons()}{this.renderInfoWindow()}</Map></div>);}
}PolygonEdit.propTypes = {isGroup: PropTypes.bool, // 是:data 为单个 polygon 数据;否: data 为多个 polygon 数据data: PropTypes.array,onCancle: PropTypes.func,onConfirm: PropTypes.func,
};
PolygonEdit.defaultProps = {isGroup: true,data: [],onCancle: () => {},onConfirm: () => {},
};export default PolygonEdit;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60135.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习中的Pixel Shuffle和Pixel Unshuffle:图像超分辨率的秘密武器

在深度学习的计算机视觉任务中&#xff0c;提升图像分辨率和压缩特征图是重要需求。Pixel Shuffle和Pixel Unshuffle是在超分辨率、图像生成等任务中常用的操作&#xff0c;能够通过转换空间维度和通道维度来优化图像特征表示。本篇文章将深入介绍这两种操作的原理&#xff0c;…

Unity类银河战士恶魔城学习总结(P132 Merge skill tree with skill Manager 把技能树和冲刺技能相组合)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了解锁技能后才可以使用技能&#xff0c;先完成了冲刺技能的锁定解锁 Dash_Skill.cs using System.Collections; using System…

正则表达式完全指南,总结全面通俗易懂

目录 元字符 连接符 限定符 定位符 修饰符&#xff08;标记&#xff09; 运算符优先级 普通字符集及其替换 零宽断言 正向先行断言 负向先行断言 正向后发断言 负向后发断言 捕获组 普通捕获组 命名捕获组 PS:非捕获组 正则表达式在线测试: 正则在线测试工具 …

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言 主要功能如下&#xff1a; 1.实现文件夹的下载和删除&#xff0c;网上很多资料都是单独对某个路径的文件操作的&#xff0c;并不能对文件夹操作 2.实现目标机中含中文名称自动转码&#xff0c;有些系统编码方式不同&#xff0c;下载出来的文件会乱码 3.实现ftp功能…

HCIP --OSI七层参考模型回顾、TCP/UDP协议复习

目录 一、OSI 二、重要的三个协议报头格式 名词注解 MTU 封装 解封装 PDU ARP DNS TCP/IP与OSI的区别 三、数据包转发过程 四、获取目标ip地址方式 五、获取目标mac地址方式 六、交换机的工作原理 七、TCP/UDP TCP&#xff08;Transmission Control Protocol&a…

物联网智能技术的深入探讨与案例分析

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Keil基于ARM Compiler 5的工程迁移为ARM Compiler 6的工程

环境&#xff1a; keil版本为5.38&#xff0c;版本务必高于5.30 STM32F4的pack包版本要高于2.9 软件包下载地址&#xff1a;https://zhuanlan.zhihu.com/p/262507061 一、更改Keil中编译器 更改后编译&#xff0c;会报很多错&#xff0c;先不管。 二、更改头文件依赖 观察…

9.《滑动窗口篇》---①长度最小的子数组(中等)

滑动窗口推导过程 我们不能说一上来就知道这个题目用滑动窗口&#xff0c;然后就使用滑动窗口的方法来做这个题目。 首先我们想到的应该是暴力解法。 接着再优化为滑动窗口 由于数字都是 ≥ 0 的数。因此累加的数越多。和越大。 因此right往后遍历的时候。当发现sum > targe…

Marin说PCB之电源完整性之电源网络的PDN仿真CST---04

小编我最近都要忙疯了&#xff0c;好不容易去韩国出个差&#xff0c;打算不忙的时候去首尔看看韩国的美女们&#xff0c;说错了&#xff0c;是看美景啊。谁料想韩国分公司的SI同事的李相赫同志由于结婚请假了一个多月啊&#xff0c;他倒是挺爽啊&#xff0c;和老婆去度蜜月了&a…

视频融合×室内定位×数字孪生

随着物联网技术的迅猛发展&#xff0c;室内定位与视频融合技术在各行各业中得到了广泛应用。不仅能够提供精确的位置信息&#xff0c;还能通过实时视频监控实现全方位数据的可视化。 与此同时&#xff0c;数字孪生等技术的兴起为智慧城市、智慧工厂等应用提供了强大支持&#…

git push时报错! [rejected] master -> master (fetch first)error: ...

错误描述&#xff1a;在我向远程仓库push代码时&#xff0c;即执行 git push origin master命令时发生的错误。直接上错误截图。 错误截图 错误原因&#xff1a; 在网上查了许多资料&#xff0c;是因为Git仓库中已经有一部分代码&#xff0c;它不允许你直接把你的代码覆盖上去…

概念解读|K8s/容器云/裸金属/云原生...这些都有什么区别?

随着容器技术的日渐成熟&#xff0c;不少企业用户都对应用系统开展了容器化改造。而在容器基础架构层面&#xff0c;很多运维人员都更熟悉虚拟化环境&#xff0c;对“容器圈”的各种概念容易混淆&#xff1a;容器就是 Kubernetes 吗&#xff1f;容器云又是什么&#xff1f;容器…

【Android】线程池的解析

引言 在Android当中根据用途分为主线程与子线程&#xff0c;主线程当中主要处理与界面相关的操作&#xff0c;子线程主要进行耗时操作。除了Thread本身以外&#xff0c;在Android当中还有很多扮演者线程的角色&#xff0c;比如AsyncTask&#xff08; 底层为线程池&#xff0c;…

本地音乐服务器(三)

6. 删除音乐模块设计 6.1 删除单个音乐 1. 请求响应设计 2. 开始实现 首先在musicmapper新增操作 Music findMusicById(int id);int deleteMusicById(int musicId); 其次新增相对应的.xml代码&#xff1a; <select id"findMusicById" resultType"com.exa…

Spring Boot图书馆管理系统:疫情中的管理利器

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了疫情下图书馆管理系统的开发全过程。通过分析疫情下图书馆管理系统管理的不足&#xff0c;创建了一个计算机管理疫情下图书馆管理系统的方案。文章介绍了疫情下图…

集群聊天服务器(7)数据模块

目录 Mysql数据库代码封装头文件与源文件 Mysql数据库代码封装 业务层代码不要直接写数据库&#xff0c;因为业务层和数据层的代码逻辑也想完全区分开。万一不想存储mysql&#xff0c;想存redis的话&#xff0c;就要改动大量业务代码。解耦合就是改起来很方便。 首先需要安装m…

Linux第93步_Linux内核的LED灯驱动

Linux内核的LED灯驱动采用platfomm框架&#xff0c;因此我们只需要按照要求在“设备树文件”中添加相应的LED节点即可。 1 、通过“linux内核图形化配置界面”令“CONFIG_LEDS_GPIOy” 1)、打开终端&#xff0c;输入“cd linux/atk-mp1/linux/my_linux/linux-5.4.31/回车”&a…

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

红外相机和RGB相机外参标定 - 无需标定板方案

1. 动机 在之前的文章中红外相机和RGB相机标定&#xff1a;实现两种模态数据融合_红外相机标定-CSDN博客 &#xff0c;介绍了如何利用标定板实现外参标定&#xff1b;但实测下来发现2个问题&#xff1a; &#xff08;1&#xff09;红外标定板尺寸问题&#xff0c;由于标定板小…

android:taskAffinity 对Activity退出时跳转的影响

android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中&#xff0c;任务栈&#xff08;Task&#xff09;是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…