Google 地图 API,标记 onClick 侦听器未按预期工作
Google Maps API, Marker onClick listener not working as intended
现在我正在尝试制作一张地图,显示印度尼西亚的所有医院(以及稍后关于 covid 病例的信息),到目前为止,我已经能够从 json 文件中成功获取位置并将其映射到地图上。我的地图有一个按钮,如果你点击它,印度尼西亚的所有医院都会作为标记显示在地图上。我现在想做的是当用户单击特定标记时弹出医院名称的信息窗口。
我是如何尝试接近它的:
为所有医院标记创建一个状态布尔数组,以查看医院是否已被单击
如果已单击医院,则输出带有医院名称的信息窗口。
问题:
似乎当我单击按钮以显示印度尼西亚的所有医院时,它会将状态布尔数组更新为全部为真。我不确定为什么会这样,当我点击一个特定的标记时,状态数组没有改变。
如果您需要完整代码,这是我的 git 存储库:https://github.com/ktanojo17505/google-map-react
这是我的状态:
state = {
address: "",
city: "",
area: "",
state: "",
zoom: 11,
height: 400,
mapPosition: {
lat: 0,
lng: 0
},
markerPosition: {
lat: 0,
lng: 0
},
placeHospitals: false,
Hospitals: [],
didClickHospital: []
};
这是我的构造函数:
constructor(props) {
super(props);
var HospitalLocations = [];
var clickHospital = [];
var position;
var hospitalName;
var id;
for (let index = 0; index < HospitalData.hospitals.length; ++index) {
id = index;
var latitude = HospitalData.hospitals[index].latitude;
var longitude = HospitalData.hospitals[index].longitude;
position = { latitude, longitude };
hospitalName = HospitalData.hospitals[index].nama;
var entry = { id, position, hospitalName };
HospitalLocations.push(entry);
clickHospital.push(false);
}
this.state.Hospitals = HospitalLocations;
this.state.didClickHospital = clickHospital;
}
这是我的return
return (
<div style={{ padding: "1rem", margin: "0 auto", maxWidth: 1000 }}>
<h1>Google Maps Basic</h1>
<Descriptions bordered>
<Descriptions.Item label="City">{this.state.city}</Descriptions.Item>
<Descriptions.Item label="Area">{this.state.area}</Descriptions.Item>
<Descriptions.Item label="State">
{this.state.state}
</Descriptions.Item>
<Descriptions.Item label="Address">
{this.state.address}
</Descriptions.Item>
</Descriptions>
<MapWithAMarker
googleMapURL={
"https://maps.googleapis.com/maps/api/js?key=" +
config.GOOGLE_API_KEY +
"&v=3.exp&libraries=geometry,drawing,places"
}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
<div style={{ marginTop: "2.5rem" }}>
<Button onClick={this.placeHospitals}>Hospitals</Button>
</div>
</div>
);
带标记的地图
const MapWithAMarker = withScriptjs(
withGoogleMap(props => (
<div>
<GoogleMap
defaultZoom={this.state.zoom}
defaultCenter={{
lat: this.state.mapPosition.lat,
lng: this.state.mapPosition.lng
}}
options={options}
onClick={this.placeMarker}
>
<Marker
draggable={true}
onDragEnd={this.onMarkerDragEnd}
position={{
lat: this.state.markerPosition.lat,
lng: this.state.markerPosition.lng
}}
>
<InfoWindow>
<div>{this.state.address}</div>
</InfoWindow>
</Marker>
{this.state.placeHospitals &&
this.state.Hospitals.map(hospitalLoc => ( // Place the locations if Hospitals Button is clicked
<Marker
draggable={false}
position={{
lat: hospitalLoc.position.latitude,
lng: hospitalLoc.position.longitude
}}
key={hospitalLoc.id}
onClick={this.clickHospital(hospitalLoc.id)} // Change the state of the Hospital InfoWindow
>
{/* {this.state.didClickHospital[index] && ( // If true output an infowindow of the hospital name
<InfoWindow>
<div>{hospitalLoc.name}</div>
</InfoWindow>
)} */}
</Marker>
))}
<AutoComplete
style={{
width: "100%",
height: "40px",
paddingLeft: 16,
marginTop: 2,
marginBottom: "2rem"
}}
types={["(regions)"]}
onPlaceSelected={this.onPlaceSelected}
/>
</GoogleMap>
</div>
))
);
点击医院
clickHospital = id => {
console.log("clicked");
// var tempClickHospital = this.state.didClickHospital;
// console.log(tempClickHospital[index]);
// tempClickHospital[index] = !tempClickHospital[index];
// console.log(tempClickHospital[index]);
// this.setState({ didClickHospital: tempClickHospital });
// console.log(this.state.didClickHospital);
};
这是我的代码的输出(在点击医院之前)1
这是我的代码的输出(点击医院后)2
如果有人能指出我做错了什么,那将很有帮助,谢谢!
您可以直接映射 json 文件中的每个数据,以创建一个包含 <InfoWindow>
的单独 <Marker>
。
这里有一个 working sample code 和下面关于如何执行此操作的代码片段:
import React, { Component } from "react";
import {
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from "react-google-maps";
//import the json data of your hospital info
import data from "./data.json";
import "./style.css";
class Map extends Component {
constructor(props) {
super(props);
this.state = {
hospitalId: "",
addMarkerBtn: false
};
}
addMarkerFunction = () => {
this.setState({
addMarkerBtn: true
});
};
handleToggleOpen = id => {
this.setState({
hospitalId: id
});
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
defaultCenter={{ lat: -6.208763, lng: 106.845599 }}
defaultZoom={16}
>
{this.state.addMarkerBtn === true &&
data.map(hospital => (
<Marker
key={hospital.id}
position={{ lat: hospital.lat, lng: hospital.lng }}
onClick={() => this.handleToggleOpen(hospital.id)}
>
{this.state.hospitalId === hospital.id && (
<InfoWindow
onCloseClick={this.props.handleCloseCall}
options={{ maxWidth: 100 }}
>
<span>{hospital.id}</span>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
));
return (
<div>
<button id="addMarker" onClick={() => this.addMarkerFunction()}>
Add Marker
</button>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: "500px" }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;
现在我正在尝试制作一张地图,显示印度尼西亚的所有医院(以及稍后关于 covid 病例的信息),到目前为止,我已经能够从 json 文件中成功获取位置并将其映射到地图上。我的地图有一个按钮,如果你点击它,印度尼西亚的所有医院都会作为标记显示在地图上。我现在想做的是当用户单击特定标记时弹出医院名称的信息窗口。
我是如何尝试接近它的: 为所有医院标记创建一个状态布尔数组,以查看医院是否已被单击 如果已单击医院,则输出带有医院名称的信息窗口。
问题: 似乎当我单击按钮以显示印度尼西亚的所有医院时,它会将状态布尔数组更新为全部为真。我不确定为什么会这样,当我点击一个特定的标记时,状态数组没有改变。
如果您需要完整代码,这是我的 git 存储库:https://github.com/ktanojo17505/google-map-react
这是我的状态:
state = {
address: "",
city: "",
area: "",
state: "",
zoom: 11,
height: 400,
mapPosition: {
lat: 0,
lng: 0
},
markerPosition: {
lat: 0,
lng: 0
},
placeHospitals: false,
Hospitals: [],
didClickHospital: []
};
这是我的构造函数:
constructor(props) {
super(props);
var HospitalLocations = [];
var clickHospital = [];
var position;
var hospitalName;
var id;
for (let index = 0; index < HospitalData.hospitals.length; ++index) {
id = index;
var latitude = HospitalData.hospitals[index].latitude;
var longitude = HospitalData.hospitals[index].longitude;
position = { latitude, longitude };
hospitalName = HospitalData.hospitals[index].nama;
var entry = { id, position, hospitalName };
HospitalLocations.push(entry);
clickHospital.push(false);
}
this.state.Hospitals = HospitalLocations;
this.state.didClickHospital = clickHospital;
}
这是我的return
return (
<div style={{ padding: "1rem", margin: "0 auto", maxWidth: 1000 }}>
<h1>Google Maps Basic</h1>
<Descriptions bordered>
<Descriptions.Item label="City">{this.state.city}</Descriptions.Item>
<Descriptions.Item label="Area">{this.state.area}</Descriptions.Item>
<Descriptions.Item label="State">
{this.state.state}
</Descriptions.Item>
<Descriptions.Item label="Address">
{this.state.address}
</Descriptions.Item>
</Descriptions>
<MapWithAMarker
googleMapURL={
"https://maps.googleapis.com/maps/api/js?key=" +
config.GOOGLE_API_KEY +
"&v=3.exp&libraries=geometry,drawing,places"
}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
<div style={{ marginTop: "2.5rem" }}>
<Button onClick={this.placeHospitals}>Hospitals</Button>
</div>
</div>
);
带标记的地图
const MapWithAMarker = withScriptjs(
withGoogleMap(props => (
<div>
<GoogleMap
defaultZoom={this.state.zoom}
defaultCenter={{
lat: this.state.mapPosition.lat,
lng: this.state.mapPosition.lng
}}
options={options}
onClick={this.placeMarker}
>
<Marker
draggable={true}
onDragEnd={this.onMarkerDragEnd}
position={{
lat: this.state.markerPosition.lat,
lng: this.state.markerPosition.lng
}}
>
<InfoWindow>
<div>{this.state.address}</div>
</InfoWindow>
</Marker>
{this.state.placeHospitals &&
this.state.Hospitals.map(hospitalLoc => ( // Place the locations if Hospitals Button is clicked
<Marker
draggable={false}
position={{
lat: hospitalLoc.position.latitude,
lng: hospitalLoc.position.longitude
}}
key={hospitalLoc.id}
onClick={this.clickHospital(hospitalLoc.id)} // Change the state of the Hospital InfoWindow
>
{/* {this.state.didClickHospital[index] && ( // If true output an infowindow of the hospital name
<InfoWindow>
<div>{hospitalLoc.name}</div>
</InfoWindow>
)} */}
</Marker>
))}
<AutoComplete
style={{
width: "100%",
height: "40px",
paddingLeft: 16,
marginTop: 2,
marginBottom: "2rem"
}}
types={["(regions)"]}
onPlaceSelected={this.onPlaceSelected}
/>
</GoogleMap>
</div>
))
);
点击医院
clickHospital = id => {
console.log("clicked");
// var tempClickHospital = this.state.didClickHospital;
// console.log(tempClickHospital[index]);
// tempClickHospital[index] = !tempClickHospital[index];
// console.log(tempClickHospital[index]);
// this.setState({ didClickHospital: tempClickHospital });
// console.log(this.state.didClickHospital);
};
这是我的代码的输出(在点击医院之前)1
这是我的代码的输出(点击医院后)2
如果有人能指出我做错了什么,那将很有帮助,谢谢!
您可以直接映射 json 文件中的每个数据,以创建一个包含 <InfoWindow>
的单独 <Marker>
。
这里有一个 working sample code 和下面关于如何执行此操作的代码片段:
import React, { Component } from "react";
import {
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from "react-google-maps";
//import the json data of your hospital info
import data from "./data.json";
import "./style.css";
class Map extends Component {
constructor(props) {
super(props);
this.state = {
hospitalId: "",
addMarkerBtn: false
};
}
addMarkerFunction = () => {
this.setState({
addMarkerBtn: true
});
};
handleToggleOpen = id => {
this.setState({
hospitalId: id
});
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
defaultCenter={{ lat: -6.208763, lng: 106.845599 }}
defaultZoom={16}
>
{this.state.addMarkerBtn === true &&
data.map(hospital => (
<Marker
key={hospital.id}
position={{ lat: hospital.lat, lng: hospital.lng }}
onClick={() => this.handleToggleOpen(hospital.id)}
>
{this.state.hospitalId === hospital.id && (
<InfoWindow
onCloseClick={this.props.handleCloseCall}
options={{ maxWidth: 100 }}
>
<span>{hospital.id}</span>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
));
return (
<div>
<button id="addMarker" onClick={() => this.addMarkerFunction()}>
Add Marker
</button>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: "500px" }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;