如何使用左侧的复选框从地图中删除标记?
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='&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;
}
...
这是我正在开发的应用程序。我的目标是在地图上显示冲浪点及其当前风速和难度级别(基于风速的高低)
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='&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;
}
...