React-leaflet在ant-design pro中的基本使用

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

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

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

 

1、react-leaflet顯示多個marker點並顯示多行popupreact

1.注意點:安裝leaflet。  命令:npm install leafletgit

 

2.裝好環境之後這裏有兩個難點,①marker圖標從新引入。②popup多行顯示。github

由於以前有踩過vue結合leaflet的坑、因此第一個問題此次跟vue裏面從新引用圖標同樣解決了。第二個問題其實也不難、就是要靈活一點去試吧。由於官方文檔沒有寫這種狀況,只是很簡單的示例。我先着重貼一下解決方案的代碼、後面有總體代碼結合理解。最後有我本身整理的github連接能夠方便在實際開發中參考。npm

效果:antd

①。解決marker圖標從新引入,第一import Leaflet,第二把leaflet模塊中的markers文件夾複製到src路徑下的asset靜態資源文件夾中,第三從新引入圖標。less

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,這樣在第二步進行處理的時候就能夠分開與樣式融合到一塊兒。第二步處理popupdom

//處理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

 

2、使用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,會持續更新豐富。

相關文章
相關標籤/搜索