Javascript 将点添加到点列表并在地图上重新渲染
所以基本上我想做的是让用户双击地图,然后用一些信息创建一个新的点。当他们单击“提交”时,应将该点添加到状态(或更高版本的数据库),然后使用正确的信息重新提交地图。这就是我到目前为止所做的,我错在哪里: App.jsJavascript 将点添加到点列表并在地图上重新渲染,javascript,reactjs,leaflet,react-leaflet,Javascript,Reactjs,Leaflet,React Leaflet,所以基本上我想做的是让用户双击地图,然后用一些信息创建一个新的点。当他们单击“提交”时,应将该点添加到状态(或更高版本的数据库),然后使用正确的信息重新提交地图。这就是我到目前为止所做的,我错在哪里: App.js import './App.css'; import * as React from "react"; import { ChakraProvider } from "@chakra-ui/react"; import { MapContain
import './App.css';
import * as React from "react";
import { ChakraProvider } from "@chakra-ui/react";
import { MapContainer, TileLayer, Marker, Popup, useMapEvents, useMap } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import * as L from 'leaflet';
import SearchBar from './SearchBar';
import CovidPoint from './CovidPoint';
import LocationMarkers from './LocationMarkers';
class App extends React.Component {
constructor(props){
super(props)
this.state = {
map: null,
points: [<CovidPoint
position={[43.653226, -79.3831843]}
name="point1"
information="random point"
input = {false}
></CovidPoint>,
<CovidPoint
position={[50.653226, -79.3831843]}
name="point2"
information="random point"
input = {true}
></CovidPoint>]
}
}
changePos = (pos, zoom) => {
const {map} = this.state;
if (map) map.flyTo(pos, zoom);
}
fetchPoints = (newPoints) => {
this.setState({points: newPoints})
this.state.points.length > 0 && this.state.points.map(
(point) => {
return point
}
)
}
render() {
return (
<div className="App">
<div id="title">
<h1>CovidStopSpots</h1>
<p>A responsive tracker for Covid-19.</p>
</div>
<div id="map">
<MapContainer
id="1"
center={[43.653226, -79.3831843]}
zoom={13}
scrollWheelZoom={false}
whenCreated={(map) => this.setState({ map })}
style={{ height: "100vh " }}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{this.state.points.length > 0 && this.state.points.map(
(point) => {
return point
}) }
{/* <CovidPoint
position={[43.653226, -79.3831843]}
name="point1"
information="random point"
></CovidPoint>
<CovidPoint
position={[50.653226, -79.3831843]}
name="point2"
information="random point"
></CovidPoint> */}
<LocationMarkers points={this.state.points} fetchPoints={this.fetchPoints}></LocationMarkers>
</MapContainer>
</div>
</div>
);
}
}
export default App;
import'/App.css';
从“React”导入*作为React;
从“@chakra ui/react”导入{ChakraProvider}”;
从“react传单”导入{MapContainer,TileLayer,Marker,Popup,useMapEvents,useMap}
导入“传单/目录/传单.css”
从“传单”中输入*作为L;
从“./SearchBar”导入搜索栏;
从“./CovidPoint”导入CovidPoint;
从“/LocationMarkers”导入LocationMarkers;
类应用程序扩展了React.Component{
建造师(道具){
超级(道具)
此.state={
map:null,
点数:[,,
]
}
}
更改位置=(位置,缩放)=>{
const{map}=this.state;
if(map)map.flyTo(pos,缩放);
}
fetchPoints=(newPoints)=>{
this.setState({points:newPoints})
this.state.points.length>0&&this.state.points.map(
(点)=>{
返回点
}
)
}
render(){
返回(
共变顶点
一种针对新冠病毒-19的响应性跟踪器
this.setState({map})}
样式={{高度:“100vh”}
>
{this.state.points.length>0&&this.state.points.map(
(点)=>{
返回点
}) }
{/*
*/}
);
}
}
导出默认应用程序;
LocationMarkers.js
import { useState } from "react";
import { useMapEvents } from "react-leaflet";
import CovidPoint from "./CovidPoint";
function LocationMarkers(props) {
const [position, setPosition] = useState([]);
useMapEvents({
dblclick(ev) {
console.log("double clicked");
const { lat, lng } = ev.latlng;
setPosition([lat, lng]);
const newPoints = [...props.points];
console.log(newPoints);
newPoints.push(<CovidPoint position={position} input={true}></CovidPoint>);
props.fetchPoints(newPoints);
}
});
return null;
}
export default LocationMarkers;
从“react”导入{useState};
从“react传单”导入{useMapEvents};
从“/CovidPoint”导入CovidPoint;
功能定位标记(道具){
const[position,setPosition]=useState([]);
useMapEvents({
dblclick(ev){
console.log(“双击”);
常数{lat,lng}=ev.latlng;
设定位置([lat,lng]);
const newPoints=[…props.points];
console.log(newPoints);
newPoints.push();
道具。获取点(newPoints);
}
});
返回null;
}
导出默认位置标记;
CovidPoint.js
import React from "react";
import { Marker, Popup } from "react-leaflet";
import L from "leaflet";
import { ChakraProvider, Button, Input} from "@chakra-ui/react";
class CovidPoint extends React.Component {
constructor(props) {
super(props);
this.state = {
position: this.props.position,
name: this.props.name,
input: this.props.input,
information: this.props.information,
key: this.props.key
};
}
pushPoint(name, info){
//push to the database
console.log("pushed to db", name, info)
this.setState({input: false})
}
GetType = (icon) => {
if (this.state.input === true){
return (
console.log("input point"),
<Marker position={this.state.position} icon={icon}>
<Popup>
Name: <Input size="sm" variant="outline" placeholder="Name" onChange={ev => {this.setState({name: ev.target.value})}}/> <br />
Case Status: <Input size="sm" variant="outline" placeholder="Case Status" onChange={ev => {this.setState({information: ev.target.value})}}/> <br />
<Button size = "xs" variant="solid" colorScheme="twitter" onClick={ev => {
if (this.state.name != "" && this.state.information != ""){
this.pushPoint(this.state.name, this.state.information);
}}}> Submit </Button>
</Popup>
</Marker>
)
}
return (
console.log("normal point"),
<Marker position={this.props.position} icon={icon}>
<Popup>
Name: {this.state.name} <br />
position: {this.state.position} <br />
Case Status: {this.state.information}
</Popup>
</Marker>
)
}
render() {
const covidIcon = L.icon({
iconUrl:
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Redpoint.svg/768px-Redpoint.svg.png",
iconSize: [30, 30], // size of the icon
iconAnchor: [0, 0], // point of the icon which will correspond to marker's location
popupAnchor: [0, 0] // point from which the popup should open relative to the iconAnchor
});
return (
<ChakraProvider>
<div>
{this.GetType(covidIcon)}
</div>
</ChakraProvider>
);
}
}
export default CovidPoint;
从“React”导入React;
从“反应传单”导入{标记,弹出};
从“传单”中输入L;
从“@chakra ui/react”导入{脉轮提供者,按钮,输入};
类CovidPoint扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
位置:this.props.position,
名称:this.props.name,
输入:this.props.input,
信息:this.props.information,
钥匙:这个。道具。钥匙
};
}
推送点(名称、信息){
//推送到数据库
日志(“推送到数据库”,名称,信息)
this.setState({input:false})
}
GetType=(图标)=>{
if(this.state.input==true){
返回(
console.log(“输入点”),
名称:{this.setState({Name:ev.target.value}}}}/>
案例状态:{this.setState({information:ev.target.value}}}/>
{
if(this.state.name!=“”&this.state.information!=“”){
this.pushPoint(this.state.name、this.state.information);
}}}>提交
)
}
返回(
console.log(“正常点”),
名称:{this.state.Name}
位置:{this.state.position}
案例状态:{this.state.information}
)
}
render(){
常数共价键=L.icon({
iconUrl:
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Redpoint.svg/768px-Redpoint.svg.png",
图标大小:[30,30],//图标的大小
iconAnchor:[0,0],//将对应于标记位置的图标点
popupAnchor:[0,0]//相对于iconAnchor打开弹出窗口的点
});
返回(
{this.GetType(covidIcon)}
);
}
}
导出默认共点;
另外,我当前遇到的错误是
TypeError:cannotread属性'lat'为null
,当我双击地图时会发生这种情况。不知道为什么会这样。任何帮助都将不胜感激。现在您正在创建一个JSX元素数组,在我看来,这会使事情变得不必要的复杂。事实上,这比一开始听起来要简单得多
您希望使用其弹出窗口存储有关位置的信息。
因此,您的数据将
function LocationMarkers() {
const [locations, setLocations] = useState(
[
{
latlng: [43.653226, -79.3831843],
name: "point1",
caseStatus: "random point1"
}
],
{
latlng: [50.653226, -79.3831843],
name: "point2",
caseStatus: "random point2"
}
);
useMapEvents({
dblclick(ev) {
const { lat, lng } = ev.latlng;
const newLocations = [...locations];
newLocations.push({ latlng: [lat, lng], name: "", caseStatus: "" });
setLocations(newLocations);
}
});
return <CovidPoint locations={locations} setLocations={setLocations} />;
}
函数位置标记(){
常量[位置,设置位置]=使用状态(
[
{
拉丁语:[43.653226,-79.3831843],
名称:“点1”,
案例状态:“随机点1”
}
],
{
拉丁语:[50.653226,-79.3831843],
名称:“点2”,
案例状态:“随机点2”
}
);
useMapEvents({
dblclick(ev){
常数{lat,lng}=ev.latlng;
const newLocations=[…位置];
推送({latlng:[lat,lng],名称:,案例状态:});
设置位置(新位置);
}
});
返回;
}
- 每次在地图上添加点时,都会将一个新的位置对象推送到位置阵列,该位置对象包含开头的坐标,并承载稍后要添加的其他属性
- 将位置和设置位置作为道具传递给CovidPoint,以便能够使用位置索引从此处添加、编辑名称和案例状态
- 那么在你的共点组合中,你不需要任何状态
const { locations, setLocations } = this.props; return ( locations.length > 0 && locations.map(({ latlng, name, caseStatus }, index) => ( <Marker position={latlng} icon={covidIcon} key={index}> <Popup> Name: <input placeholder="Name" value={name} onChange={(e) => { const newLocations = [...locations]; const newLocationObj = { ...newLocations[index] }; newLocationObj.name = e.target.value; newLocations[index] = newLocationObj; setLocations(newLocations); }} /> <br /> <br /> Case Status: <input value={caseStatus} placeholder="Case Status" onChange={(e) => { const newLocations = [...locations]; const newLocationObj = { ...newLocations[index] }; newLocationObj.caseStatus = e.target.value; newLocations[index] = newLocationObj; setLocations(newLocations); }} /> </Popup> </Marker> )) );