react-leaflet的github地址:https://github.com/PaulLeCam/react-leaflet

react-leaflet-markercluster点聚合github地址  :https://github.com/YUzhva/react-leaflet-markercluster

本篇案例github地址:https://github.com/GugaLiz/ant-design-react-ProDemo

一、react-leaflet显示多个marker点并显示多行popup

1.注意点:安装leaflet。  命令:npm install leaflet

2.装好环境以后这里有两个难点,①marker图标重新引入。②popup多行显示。

因为之前有踩过vue结合leaflet的坑、所以第一个问题这次跟vue里面重新引用图标一样解决了。第二个问题其实也不难、就是要灵活一点去试吧。因为官方文档没有写这种情况,只是很简单的示例。我先着重贴一下解决方案的代码、后面有整体代码结合理解。最后有我自己整理的github链接可以方便在实际开发中参考。

效果:

①。解决marker图标重新引入,第一import Leaflet,第二把leaflet模块中的markers文件夹复制到src路径下的asset静态资源文件夹中,第三重新引入图标。

import L from 'leaflet';   //引入leaflet
import { Map, TileLayer,Marker,Popup } from 'react-leaflet';
import "leaflet/dist/leaflet.css";
//把图标重新引入
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.imagePath = ''
L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('../../assets/markers/marker-icon-2x.png'),
  iconUrl: require('../../assets/markers/marker-icon.png'),
  shadowUrl: require('../../assets/markers/marker-shadow.png')
})

②。解决第二问题,第一把每一个marker需要多行显示的popup的每一行都做成一个obj,这样在第二步进行处理的时候就可以分开与样式融合到一起。第二步处理popup

//处理popup的内容

let popupContent = [{key:city,string:`城市:${city}`},
{key:name,string:`基站名称:${name}`},
{key:lng,string:`经度:${lng}`},
{key:lat,string:`纬度:${lat}`},
{key:district,string:`地区:${district}`},
{key:address,string:`地址:${address}`},
{key:maintainer,string:`维护人员:${maintainer}`},
]
 
//处理popup的显示
const PopupMarker = ({ children,position }) => {
const items = children.map((item) => (<span key={item.key}>{item.string}<br /></span>))   //把每一行要显示的数据与样式融合为一个item方便调用显示
return <Marker position={position}>
<Popup><div>
{items}
</div></Popup>
</Marker>
}

整体代码参上:

import React, { PureComponent, Fragment } from 'react';
import { render } from 'react-dom'; import { connect } from 'dva';
import { Row, Col, Card, Tooltip, Menu, Dropdown, Icon, Button,Layout } from 'antd'; import styles from './MapTest.less'; import L from 'leaflet';
import { Map, TileLayer,Marker,Popup } from 'react-leaflet'; import "leaflet/dist/leaflet.css"; const {Content} = Layout; //把图标重新引入
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.imagePath = ''
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('../../assets/markers/marker-icon-2x.png'),
iconUrl: require('../../assets/markers/marker-icon.png'),
shadowUrl: require('../../assets/markers/marker-shadow.png')
}) //处理每一个marker的显示
const PopupMarker = ({ children,position }) => {
const items = children.map((item) => (<span key={item.key}>{item.string}<br /></span>)) return <Marker position={position}>
<Popup><div>
{items}
</div></Popup>
</Marker> }
//处理markerlist
const MarkersList = ({markers}) => {
const items = markers.map(({ key,...props}) => (
<PopupMarker key={key} {...props} />
))
return <div>{items}</div>
} export default class SiteMap extends PureComponent { render() { const position = [22.7047, 113.302]; //中心点 //模拟数据
const dataList = [];
for (let i = 0; i < 46; i += 1) {
dataList.push({
id: i,
Province: '',
Name: `site ${i}`,
Lat: 22.7047 + `${i}`,
Lng: 113.302 - `${i}`,
currentValue: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 2,
purchaseDate: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
create_time: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
progress: Math.ceil(Math.random() * 100),
Province: Math.floor(Math.random() * 10) % 2 ? '省份1' : '省份2',
City: Math.floor(Math.random() * 10) % 2 ? '城市1' : '城市2',
});
}
let cellPoints = []; dataList.map(item => {
let lng = Number.parseFloat(item.Lng);
let lat = Number.parseFloat(item.Lat);
let name = item.Name;
let city = item.City || '';
let district = item.District || '';
let address = item.Address || '';
let maintainer = item.Maintainer || '';
let popupContent = [{key:city,string:`城市:${city}`},
{key:name,string:`基站名称:${name}`},
{key:lng,string:`经度:${lng}`},
{key:lat,string:`纬度:${lat}`},
{key:district,string:`地区:${district}`},
{key:address,string:`地址:${address}`},
{key:maintainer,string:`维护人员:${maintainer}`},
]
cellPoints.push({key:name,position:[lat, lng],children:popupContent});
}); const style= {
width: '100%',
height: '600px',
} return (
<Content>
<div className="ant-card-bordered" style={style}> <Map center={position} zoom={13} style={{width: '100%', height: '100%'}}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/> <MarkersList markers={cellPoints} /> </Map>
</div>
</Content>
);
}
}

LeafletMarker.js

二、使用react-leaflet-markercluster点聚合显示坐标点。

1.注意点:按照github上使用方法安装好。 命令:

npm install react-leaflet-markercluster
npm install leaflet.markercluster leaflet react-leaflet prop-types

2.确保两个都安装上就可以使用了、文档还蛮全的也是案例型、容易使用。我这里也只是简单引用点聚合。我这里的方式是先定义marker样式,然后引用,注意这里要在less文件里写好聚合点样式噢。

//定义聚合点样式
const createClusterCustomIcon = function (cluster) {
return L.divIcon({
html: `<span>${cluster.getChildCount()}</span>`,
className: styles.markercustom,
iconSize: L.point(40, 40, true)
});
};
//引用
<MarkerClusterGroup
spiderfyDistanceMultiplier={2}
iconCreateFunction={createClusterCustomIcon}
markers={cellPoints}
/>
//样式
/* Customising the Clustered Markers */
.markercustom {
background: #9370db;
border: 3px solid #ededed;
border-radius: 50%;
color: #ededed;
height: 40px;
line-height: 37px;
text-align: center;
width: 40px;
}
效果:
 
整体代码:(注释掉部分是实际项目中模拟数据的流通,可去github看~)

import React, { PureComponent, Fragment } from 'react';
import { render } from 'react-dom'; import { connect } from 'dva';
import { Row, Col, Card, Tooltip, Menu, Dropdown, Icon, Button,Layout } from 'antd'; import styles from './MapTest.less'; import L from 'leaflet';
import { Map, TileLayer } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster'; import "leaflet/dist/leaflet.css"; const {Content} = Layout; //把图标重新引入
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.imagePath = ''
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('../../assets/markers/marker-icon-2x.png'),
iconUrl: require('../../assets/markers/marker-icon.png'),
shadowUrl: require('../../assets/markers/marker-shadow.png')
}) // @connect(({ site, loading }) => ({
// site,
// loading: loading.models.site,
// }))
export default class SiteMap extends PureComponent {
// componentDidMount() {
// const { dispatch } = this.props;
// dispatch({
// type: 'site/fetch',
// });
// }
render() {
// const { site:{data}, loading } = this.props; const position = [22.7047, 113.302]; //const dataList = { data }.data.list;
const dataList = [];
for (let i = 0; i < 46; i += 1) {
dataList.push({
id: i,
Province: '',
Name: `site ${i}`,
Lat: 22.7047 + `${i}`,
Lng: 113.302 - `${i}`,
currentValue: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 2,
purchaseDate: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
create_time: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
progress: Math.ceil(Math.random() * 100),
Province: Math.floor(Math.random() * 10) % 2 ? '省份1' : '省份2',
City: Math.floor(Math.random() * 10) % 2 ? '城市1' : '城市2',
});
}
let cellPoints = []; const sytlep = {
width:'100%',
} dataList.map(item => {
let lng = Number.parseFloat(item.Lng);
let lat = Number.parseFloat(item.Lat);
let name = item.Name;
let city = item.City || '';
let district = item.District || '';
let Address = item.Address || '';
let maintainer = item.Maintainer || '';
let popupDiv = `<div style={stylep}>
<span>城市:${city}</span>
<br />
<span>基站名称:${name}</span>
<br />
<span>经度:${lng}</span>
<br />
<span>纬度:${lat}</span>
<br />
<span>地区:${district}</span>
<br />
<span>地址:${Address}</span>
<br />
<span>维护人员:${maintainer}</span>
<br />
</div>`
cellPoints.push({position:[lat, lng],popup:popupDiv});
}); const style= {
width: '100%',
height: '600px',
} //定义聚合点样式
const createClusterCustomIcon = function (cluster) {
return L.divIcon({
html: `<span>${cluster.getChildCount()}</span>`,
className: styles.markercustom,
iconSize: L.point(40, 40, true)
});
}; return (
<Content>
<div className="ant-card-bordered" style={style}> <Map className={styles.markercluster} center={position} zoom={13} style={{width: '100%', height: '100%'}}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/> <MarkerClusterGroup
spiderfyDistanceMultiplier={2}
iconCreateFunction={createClusterCustomIcon}
markers={cellPoints}
/> </Map>
</div>
</Content>
);
}
}

markercluster

总结:

这里要注意记得把marker的图片文件夹放入src/assets里面,不然会跑不起来的。

两种用法文档都有比较详细的代码可以参考。如果出不来效果多研究研究。

具体项目中的使用可以参考我的github的demo,会持续更新丰富。

React-leaflet在ant-design pro中的基本使用的更多相关文章

  1. Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)

    Ant Design Pro中Transfer穿梭框的实际用法(与后端交互) 该控件的属性以及属性的作用在ADP的官方文档中都有介绍,但没有讲如何与后端交互,本文旨在讲解该控件与后端的交互. Ant ...

  2. 实战 ant design pro 中的坑

    1.替换mock数据: 1.将:.roadhogrc.mock.js 中的代理模式替换 当不使用代理的时候就会将所有 /api/的链接换成 http://localhost:8080/ export ...

  3. 把antd的组件源码搬到Ant Design Pro中使用

    把组件源码搬过来后,样式死活不生效,经过1天的努力,有说less-loader的,有说webpack配置,还有说babel配置的,最后,我自己找到了方法 就是在global.less中使用@impor ...

  4. ant design pro (八)构建和发布

    一.概述 原文地址:https://pro.ant.design/docs/deploy-cn 二.详细 2.1.构建 当项目开发完毕,只需要运行一行命令就可以打包你的应用: npm run buil ...

  5. ant design pro (七)和服务端进行交互

    一.概述 原文地址:https://pro.ant.design/docs/server-cn Ant Design Pro 是一套基于 React 技术栈的单页面应用,我们提供的是前端代码和本地模拟 ...

  6. ant design pro(二)布局

    一.概述 参看地址:https://pro.ant.design/docs/layout-cn 其实在上述地址ant-design上已经有详细介绍,本文知识简述概要. 页面整体布局是一个产品最外层的框 ...

  7. Ant Design Pro快速入门

    在上一篇文章中,我们介绍了如何构建一个Ant Design Pro的环境. 同时讲解了如何启动服务并查看前端页面功能. 在本文中,我们将简单讲解如何在Ant Design Pro框架下实现自己的业务功 ...

  8. Ant Design Pro 学习笔记:数据流向

    在讲这个问题之前,有一个问题应当讲一下: Ant Design Pro / umi / dva 是什么关系? 首先是 umi / dva 的关系. umi 是一个基于路由的 react 开发框架. d ...

  9. ant design pro (十五)advanced 使用 API 文档工具

    一.概述 原文地址:https://pro.ant.design/docs/api-doc-cn 在日常开发中,往往是前后端分离的,这个时候约定好一套接口标准,前后端各自独立开发,就不会被对方的技术难 ...

  10. ant design pro (十一)advanced Mock 和联调

    一.概述 原文地址:https://pro.ant.design/docs/mock-api-cn Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路.通过预先跟服务器端约定好的 ...

随机推荐

  1. jq ajax传递json对象到服务端及contentType的用法

    目录 0.一般情况下,通过键值对的方式将参数传递到服务端 1.ajax 传递复杂json对象到服务端 2.content-Type 对asp.net mvc项目的重要性 0.一般情况下,通过键值对的方 ...

  2. Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II)

    Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II) 假设按照升序排序的数组在预先未知的某个点上进 ...

  3. Keras(五)LSTM 长短期记忆模型 原理及实例

    LSTM 是 long-short term memory 的简称, 中文叫做 长短期记忆. 是当下最流行的 RNN 形式之一 RNN 的弊端 RNN没有长久的记忆,比如一个句子太长时开头部分可能会忘 ...

  4. 【百度之星】【java大数+C++做法】hdu 6719 Strassen

    代码:递归搜索一下.java大数做法 import java.util.*; import java.math.*; import java.security.MessageDigest; publi ...

  5. CF - 1108 F MST Unification

    题目传送门 题意:在一幅图中, 问需要使得多少条边加一,使得最小生成树只有一种方案. 题解:Kruskal, sort完之后,对于相通的一个边权w,我们可以分析出来有多少边是可以被放到图里面的,然后我 ...

  6. CodeForces 103 D Time to Raid Cowavans

    Time to Raid Cowavans 题意:一共有n头牛, 每头牛有一个重量,m次询问, 每次询问有a,b 求出 a,a+b,a+2b的牛的重量和. 题解:对于m次询问,b>sqrt(n) ...

  7. 中南林业科技大学第十一届程序设计大赛 有趣的二进制 牛客网 java大数的一些方法

    链接:https://www.nowcoder.com/acm/contest/124/C来源:牛客网 题目描述 小新在学C语言的时候,邝老师告诉他double类型的数据在表示小数的时候,小数点后的有 ...

  8. Linux基础Day001-001章

    运维工作职责:(运行和维护服务器) 1.数据不能丢失, 2.保障网站7*24H正常运行,--一直运行; 3.用户体验要好,--打开网站速度要快 服务器核心硬件(硬盘,内存,CPU) 尺寸: 1U-4. ...

  9. Python 之父的解析器系列之六:给 PEG 语法添加动作

    原题 | Adding Actions to a PEG Grammar 作者 | Guido van Rossum(Python之父) 译者 | 豌豆花下猫("Python猫"公 ...

  10. Vulkan(1)用apispec生成Vulkan库

    Vulkan(1)用apispec生成Vulkan库 我的Vulkan.net库已在(https://github.com/bitzhuwei/Vulkan.net)开源,欢迎交流. apispec. ...