如何使用左侧的复选框从地图中删除标记?

How can I remove markers from the map using the checkboxes on the left?

这是我正在开发的应用程序。我的目标是在地图上显示冲浪点及其当前风速和难度级别(基于风速的高低)

https://lewisd1996.github.io/surferspotter/

我是 React 的新手,我还在不断学习。

如何使用左侧的复选框更改地图上的标记。

这是我的 SurfMap class:

import React, { Component } from 'react';
import L from 'leaflet';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import main from '../styles/main.scss';
import SpotList from "./SpotList.js";
import Spot from "./Spot.js";
import axios from 'axios';
import jsonLocations from '../jsonLocations.json';

export default class SurfMap extends Component {

    constructor() {
        super()
        this.state = {
            spots: [], //THE ARRAY THAT WILL HOLD THE LIST OF SURFING SPOTS
        }
        }

    getSpots = () => { //THE FUNCTION TO POPULATE THE LIST OF SPOTS USING AXIOS

       axios.get("https://api.jsonbin.io/b/5e8733f193960d63f0782ad5/2")
        .then(res => {
            this.setState({
                spots: res.data
            });
        });

    }

    componentDidMount(){
        this.getSpots();
    }

    render() {
        var startPosition = [36.778259, -119.417931] //STARTING POSITION OF THE MAP
        return (
            <>
            {this.state.spots.length ? 
                <Map className="map" center={startPosition} zoom={5}>
                    <TileLayer
                        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                        />
                    {this.state.spots.map (spot => //LOOP THROUGH THE LIST OF SPOTS AND CREATE A SPOT FOR EACH ONE TO BE PLOTTED ONTO THE MAP
                        <Spot {...spot} />
                    )}
                </Map>:
        <p>loading data....</p>}
      </>

        )
    }
}

这是我的地点class(地图上标出的冲浪地点):

import React, { Component, setState } from 'react'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import L from 'leaflet';
import axios from 'axios';
import main from '../styles/main.scss'

var owmApiKey = 'HIDING THIS FROM Whosebug';

var beginnerIcon = L.icon({ //SETS UP THE PIN ICON THAT IS USED TO PLOT MARKERS ON THE MAP
    iconUrl: process.env.PUBLIC_URL + '/markers/Green-marker.png',
    iconSize: [41,41],
    iconAnchor: [12.5,41],
    popupAnchor: [0, -41]
});

var intIcon = L.icon({ //SETS UP THE PIN ICON THAT IS USED TO PLOT MARKERS ON THE MAP
    iconUrl:  process.env.PUBLIC_URL + '/markers/Red-marker.png',
    iconSize: [41,41],
    iconAnchor: [12.5,41],
    popupAnchor: [0, -41]
});

var expertIcon = L.icon({ //SETS UP THE PIN ICON THAT IS USED TO PLOT MARKERS ON THE MAP
    iconUrl: process.env.PUBLIC_URL + '/markers/Purple-marker.png',
    iconSize: [41,41],
    iconAnchor: [12.5,41],
    popupAnchor: [0, -41]
});


export default class Spot extends Component {

    constructor(props) {
        super()
        this.state = {
            county_name: props.county_name,
            latitude: props.latitude,
            longitude: props.longitude,
            spot_id: props.spot_id,
            spot_name: props.spot_name,
            wind_speed: 0,
        }
    }

    getWindSpeed = (latitude, longitude) => {//THE FUNCTION TO POPULATE THE LIST OF SPOTS USING AXIOS
            axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${latitude}&appid=${owmApiKey}`)
            .then(res => {
                this.setState({
                    wind_speed: (res.data.wind.speed * 1.944)
                });
            });
    }

    componentDidMount() {
        this.getWindSpeed(this.state.latitude,this.state.longitude);
    }


    render() {
        return(
        <>
            {(() => {
            if (this.state.wind_speed < 8) {
                return (
                    <Marker position={[this.state.latitude,this.state.longitude]} icon={beginnerIcon} className="beginner-marker">
                    <Popup >
                        <p className="marker-label">{this.state.spot_name + ", " + this.state.county_name}<br/>Wind Speed: {this.state.wind_speed} knots<br/>Difficulty: Beginner</p>
                    </Popup>
                    </Marker>    
                )
            } else if (this.state.wind_speed > 8 && this.state.wind_speed < 16) {
                return (
                    <Marker position={[this.state.latitude,this.state.longitude]} icon={intIcon}  className="intermediate-marker">
                    <Popup >
                        <p className="marker-label">{this.state.spot_name + ", " + this.state.county_name}<br/>Wind Speed: {this.state.wind_speed} knots<br/>Difficulty: Intermediate</p>
                    </Popup>
                    </Marker>    
                )
            } else {
                return (
                    <Marker position={[this.state.latitude,this.state.longitude]} icon={expertIcon}  className="expert-marker">
                    <Popup >
                        <p className="marker-label">{this.state.spot_name + ", " + this.state.county_name}<br/>Wind Speed: {this.state.wind_speed} knots<br/>Difficulty: Expert</p>
                    </Popup>
                    </Marker>   
                )
            }
            })()}
            </>
        )
    }

}

我的复选框在我的控制面板中 class:

import React, { Component } from 'react';
import main from '../styles/main.scss';

export default class ControlPanel extends Component {
    render() {
        return (
            <div className="control-panel">
                <div className="form-check form-check-inline">
                    <input className="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1"></input>
                    <label className="form-check-label" htmlFor="inlineCheckbox1">Novice</label>
                </div>

                <div className="form-check form-check-inline">
                <input className="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2"></input>
                <label className="form-check-label" htmlFor="inlineCheckbox2">Intermediate</label>
                </div>

                <div className="form-check form-check-inline">
                <input className="form-check-input" type="checkbox" id="inlineCheckbox3" value="option3"></input>
                <label className="form-check-label" htmlFor="inlineCheckbox3">Expert</label>
                </div>
            </div>
        )
    }
}

我的地图和控制面板都放在我的仪表板中,然后在 App.js:

中呈现
import React, { Component } from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import main from '../styles/main.scss'
import SurfMap from './SurfMap.js'
import ControlPanel from './ControlPanel.js';
import Spot from './Spot.js';
import SpotList from './SpotList.js';

export default class Dashboard extends Component {
    render() {
        return (
            <div className="dashboard">
                <div className="dashboard__control-panel">
                    <ControlPanel />
                </div>
                    <SurfMap />
            </div>
        )
    }
}

如果你想动态改变标记,你必须在标记 json 上设置一个标志,所以如果用户按下复选框,你就可以在标记 json 上重新渲染从复选框中获取的标志。

首先,您需要使用 context 或 redux 存储关卡状态,因为您希望在没有父子关系的组件之间共享变量。

这是一种使用上下文的方法。这是您的提供者。它将存储复选框的状态。

class Provider extends Component {
  state = {
    difficulty: {
      novice: true,
      beginner: true,
      intermediate: false,
      expert: false
    }
  };

  setDifficulty = difficulty => {
    this.setState({ difficulty });
  };

  render() {
    return (
      <Context.Provider
        value={{
          difficulty: this.state.difficulty,
          setDifficulty: this.setDifficulty
        }}
      >
        {this.props.children}
      </Context.Provider>
    );
  }
}

然后您想在 ControlPanel 上本地更改级别状态,完成后更新您的全局上下文:

 class ControlPanel extends Component {

      state = { novice: true, beginner: true, intermediate: false, expert: false };

      handleInputChange = event => {
        const target = event.target;
        const checked = target.checked;
        const name = target.name;

        this.setState({
          [name]: checked
        });

        const difficulty = { ...this.state };
        difficulty[name] = checked;
        this.props.setDifficulty(difficulty);
      };

      render() {
        const levels = ["novice", "beginner", "intermediate", "expert"];

        return (
          <div className="control-panel">
            {levels.map(level => (
              <div className="form-check form-check-inline">
                <input
                  className="form-check-input"
                  type="checkbox"
                  name={level}
                  checked={this.state[level]}
                  onChange={this.handleInputChange}
                />
                <label className="form-check-label" htmlFor="inlineCheckbox1">
                  {level}
                </label>
              </div>
            ))}
          </div>
        );
      }
    }

    export default props => (
      <Context.Consumer>
        {({ setDifficulty }) => (
          <ControlPanel {...props} setDifficulty={setDifficulty} />
        )}
      </Context.Consumer>
    );

在 SurfMap 上使上下文可用:

....

 <>
    <Context.Consumer>
            {({ difficulty }) =>
              this.state.spots.map((
                spot,
                spotIndex //LOOP THROUGH THE LIST OF SPOTS AND CREATE A SPOT FOR EACH ONE TO BE PLOTTED ONTO THE MAP
              ) => (
                <Spot key={spotIndex} {...spot} difficulty={difficulty} />
              ))
            }
          </Context.Consumer>
        </>

...

终于在 Spot comp 上使用适当的条件来有条件地渲染标记。 fi 如果 wind_speed 小于 4.2 是新手,如果 wind_speed 小于 8 是初学者等等,然后继续:

    ....
        render() {
        const { spot_name, county_name, wind_speed } = this.state;
        const {
          difficulty: { novice, beginner, intermediate, expert }
        } = this.props;

        const marker = (
          <Marker
            position={[this.state.latitude, this.state.longitude]}
            icon={beginnerIcon}
            className="beginner-marker"
          >
            <Popup>
              <p className="marker-label">
                {spot_name + ", " + county_name}
                <br />
                Wind Speed: {wind_speed} knots
                <br />
                Difficulty:
                {wind_speed < 4.2
                  ? "Novice"
                  : wind_speed < 8
                  ? "Beginner"
                  : wind_speed > 8
                  ? "Intermediate"
                  : "Expert"}
              </p>
            </Popup>
          </Marker>
        );

        if (novice && !beginner) return wind_speed < 4.2 && marker;
        else if (!novice && beginner)
          return wind_speed >= 4.2 && wind_speed < 8 && marker;
        else if (novice && beginner) return wind_speed < 8 && marker;
        return null;
      }
...

Demo