如何获取每个国家/地区的地图标记数量 - ReactJS

How to get the number of map markers per country - ReactJS

我正在使用 Citybik.es API (http://api.citybik.es/) 在 Leaflet 地图上显示数据。

目前,代码显示了地图中的每个项目,但在分析之后我想稍微组织一下数据,让用户可以深入了解信息,当点击标记。像这样:

  1. 显示每个国家/地区的网络数量(每个标记代表一个网络,可以说,每个国家/地区的每个标记)
  2. 显示每个网络的站数

响应看起来像这样:

这是 JavaScript:

import React, { Component } from 'react';
import L from 'leaflet';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';

// code for map marker icon
   var myIcon = L.icon({
       iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=',
       iconSize: [25, 41],
       iconAnchor: [12.5, 41],
       popupAnchor: [0, -41]
    });

class App extends Component {
    state = {
        location: {
            lat: 51.505,
            lng: -0.09,
        },
        bikeData: [],
        haveUsersLocation: false,
        zoom: 3,
    }

//lifecycle method to get the bike information
componentDidMount() {

    fetch('https://api.citybik.es/v2/networks')
        .catch(error => {
            console.log(error)
        })
        .then(res => res.json())
        .then(response => {
            const networkData = response.networks;
            this.setState({
                bikeData: networkData
            });
        })
}


render() {
    const position = [this.state.location.lat, this.state.location.lng]
    const bikeData = this.state.bikeData;
    return (
        <Map className="map" center={position} zoom={this.state.zoom}>
            <TileLayer
                attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            {
                bikeData && bikeData.map((data) => {
                    console.log(data)
                    return (
                        <Marker
                            icon={myIcon}
                            key={data.id}
                            position={[data.location.latitude, data.location.longitude]}>
                            <Popup>
                                Name: {data.name} <br />
                                Station Details: {[data.location.city, data.location.country]}
                            </Popup>
                        </Marker>
                    )
                })
            }
        </Map>
    )
}
}

ReactDOM.render(<App/>,
    document.getElementById('root')
);

谢谢!

也许这样可以得到计数

  const networkCountByCountry = new Map();

  response.networks.forEach(network => {
    const country = network.location.country
    const countryObject = networkCountByCountry.has(country) ?   networkCountByCountry.get(country) : {
        id: country,
        count: 0
    };
    countryObject.count = countryObject.count + 1
    networkCountByCountry.set(countryObject.id, countryObject)
  }) 

 const networkCountByCountryArray = [...networkCountByCountry.values()]

然后,您可以使用点击事件来过滤到选定的国家/地区列表。

一个更完整的例子:

import L from "leaflet";
import { Map as MapLeaf, TileLayer, Marker, Popup } from "react-leaflet";

// code for map marker icon
var myIcon = L.icon({
  iconUrl:
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=",
  iconSize: [25, 41],
  iconAnchor: [12.5, 41],
  popupAnchor: [0, -41]
});

class MapDisplay extends Component {
  state = {
    location: {
      lat: 51.505,
      lng: -0.09
    },
    selectedCountry: null,
    bikeData: [],
    haveUsersLocation: false,
    zoom: 3
  };

  //lifecycle method to get the bike information
  componentDidMount() {
    fetch("https://api.citybik.es/v2/networks")
      .catch(error => {
        console.log(error);
      })
      .then(res => res.json())
      .then(response => {
        const networkData = response.networks;
        const networkCountByCountry = new Map();
        response.networks.forEach(network => {
          const country = network.location.country;
          const countryObject = networkCountByCountry.has(country)
            ? networkCountByCountry.get(country)
            : { id: country, count: 0, location: network.location };
          countryObject.count = countryObject.count + 1;
          networkCountByCountry.set(countryObject.id, countryObject);
        });
        const networkCountByCountryArray = [...networkCountByCountry.values()];
        this.setState({
          bikeData: networkData,
          bikeCountryData: networkCountByCountryArray
        });
      });
  }

  countryMarkerClick(country) {
    console.log(country);
    this.setState({ selectedCountry: country });
  }

  render() {
    const position = [this.state.location.lat, this.state.location.lng];
    if (this.state.selectedCountry) {
      const bikeData = this.state.bikeData.filter(
        network => network.location.country === this.state.selectedCountry
      );

      return (
        <MapLeaf className="map" center={position} zoom={this.state.zoom}>
          <TileLayer
            attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          {bikeData &&
            bikeData.map(data => {
              console.log(data);
              return (
                <Marker
                  icon={myIcon}
                  key={data.id}
                  position={[data.location.latitude, data.location.longitude]}
                >
                  <Popup>
                    Name: {data.name} <br />
                    Station Details:{" "}
                    {[data.location.city, data.location.country]}
                  </Popup>
                </Marker>
              );
            })}
        </MapLeaf>
      );
    }

    const bikeCountryData = this.state.bikeCountryData;
    return (
      <MapLeaf className="map" center={position} zoom={this.state.zoom}>
        <TileLayer
          attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {bikeCountryData &&
          bikeCountryData.map(data => {
            return (
              <Marker
                icon={myIcon}
                key={data.id}
                position={[data.location.latitude, data.location.longitude]}
              >
                <Popup>
                  Name: {data.id} <br />
                  Stations: {[data.count]} <br />
                  <span onClick={this.countryMarkerClick.bind(this, data.id)}>
                    {" "}
                    -->{" "}
                  </span>
                </Popup>
              </Marker>
            );
          })}
      </MapLeaf>
    );
  }
}