Как я могу удалить маркеры с карты, используя флажки слева? - PullRequest
1 голос
/ 03 апреля 2020

Вот мое приложение в процессе работы. Моя цель - показать на карте места для серфинга с текущими скоростями ветра и уровнем сложности (в зависимости от того, насколько высока скорость ветра)

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

Я новичок в React, и я все еще учусь, как я go.

Как поменять маркеры на карте с помощью моих флажков слева.

Вот мой класс SurfMap :

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>}
      </>

        )
    }
}

Вот мой класс Spot (пятна для go сёрфинга, которые нанесены на карту):

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 STACKOVERFLOW';

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>   
                )
            }
            })()}
            </>
        )
    }

}

Мои флажки хранятся в классе моей панели управления:

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>
        )
    }
}

И моя Карта и Панель управления оба помещены в мою панель управления, а затем отображаются в приложении. 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>
        )
    }
}

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Прежде всего вам необходимо сохранить состояние уровней с использованием контекста или редукса, поскольку вы хотите обмениваться переменными между компонентами без родительских и дочерних отношений.

Вот подход с использованием контекста. Вот ваш провайдер. Он будет хранить состояние флажков.

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, это новичок, если <code>wind_speed равен <8, это новичок и т. д. c и он продолжает: </p>

    ....
        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;
      }
...

Демонстрация

0 голосов
/ 03 апреля 2020

Если вы хотите изменить маркер динамически, вы должны установить флаг на маркер json, поэтому, если пользователь нажимает флажок, который вы только что сыграли, для повторного рендеринга на маркере json с флажком, полученным из флажка.

...