前言:高版本的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.props
- const l = polygons.length
- const _polygons = []
- for (let i = 0; i < l; i++) {
- const detail = polygons[i]
- if (detail.geoArea && detail.geoArea.length) {
- let _polygonType = polygonType.normal
- if (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.state
- if (!infoWindowPosition) {
- return null
- }
- return <InfoWindow
- position={{
- 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.state
- if (!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 (
- <InfoWindow
- position={position}
- visible={visible}
- isCustom={true}
- offset={[2, 2]}
- >
- {tds}
- </InfoWindow>
- );
- };
- pointRender = (extData) => {
- return (
- <div
- style={{
- 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>
- <Switch
- checkedChildren="显示地点"
- unCheckedChildren="显示地点"
- checked={pointReferShow}
- onChange={this.changePointReferShow}
- />
- </Form.Item>
- </Form>
- </ActionsForm>
- <Map {...option}>
- <Markers
- markers={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 zoneDetail
-
- return polygons
- }, [])
- }
- }
- const newData = prepareGroups(areaReferData)
- const polygons = newData.polygons
- const l = polygons.length
- const _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.state
- if(showLabels){
- if (!infoWindowPosition) {
- return null
- }
- return <InfoWindow
- position={{
- 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 (
- <div
- style={{
- 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.state
- if (!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 (
- <InfoWindow
- position={position}
- visible={visible}
- isCustom={true}
- offset={[2, 2]}
- >
- {tds}
- </InfoWindow>
- );
- };
- // polygon edit switch
- togglePolygon = (checked, e) => {
- if (checked) {
- // open edit and close add if it is drawing
- if (this.mouseTool) {
- this.mouseTool.close();
- }
- this.setState({ polygonActive: true, isDrawingPolygon: false });
- } else {
- // close edit
- this.setState({ polygonActive: false });
- }
- };
- // polygon add switch
- toggleDrawPolygon = (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 draw
- drawWhat = (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 end
- polyEditorEnd = (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 data
- isomorphicFetch(
- `//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>
- <Popconfirm
- title={
- <ZoneCascader
- adcode={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>
- <Switch
- disabled={mapEditable === "N"}
- checkedChildren="调整"
- unCheckedChildren="调整"
- checked={polygonActive}
- onChange={this.togglePolygon}
- />
- </Form.Item>
- <Form.Item>
- <Switch
- disabled={mapEditable === "N"}
- checkedChildren="新增"
- unCheckedChildren="新增"
- checked={isDrawingPolygon}
- onChange={this.toggleDrawPolygon}
- />
- </Form.Item>
- <Form.Item>
- <Dropdown
- overlay={
- <Menu onClick={this.handleMenuClick}>
- {data &&
- data.length > 0 &&
- data.map((item, index) => (
- <Menu.Item key={index}>
- <span
- onMouseOver={() => 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>
- <Switch
- checkedChildren="显示地点"
- unCheckedChildren="显示地点"
- checked={pointReferShow}
- onChange={this.changePointReferShow}
- />
- </Form.Item>
- <Form.Item>
- <Switch
- checkedChildren="显示其他区域"
- unCheckedChildren="显示其他区域"
- checked={areaReferShow}
- onChange={this.changeAreaReferShow}
- />
- </Form.Item>
- <Form.Item>
- <Switch
- checkedChildren="显示区域名称"
- 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}>
- <Markers
- markers={pointReferData}
- offset={[0,0]}
- render={this.pointRender}
- events={this.markerEvents}
- useCluster={useCluster}
- />
- {isGroup && <MouseTool events={this.toolEvents} />}
- {isGroup ? (
- <Polygon
- path={data}
- style={{ fillOpacity: 0.3, strokeOpacity: 0.5, strokeWeight: 1 }}
- events={this.polygonEvents}
- >
- <PolyEditor
- active={
- polygonActive && data.length > 0 && data.flat().length <= 100
- }
- events={this.polyEditorEvents}
- />
- </Polygon>
- ) : (
- data.map((item, index) => (
- <Polygon
- events={this.polygonEvents}
- key={index}
- path={item}
- style={{
- fillOpacity: 0.3,
- strokeOpacity: 0.5,
- strokeWeight: 1,
- }}
- />
- ))
- )}
- <Polygon
- visible={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;
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |