reactjs - 计算地图坐标之间的距离
问题描述
import React from "react";
import PlacesAutocomplete, {
geocodeByAddress,
getLatLng
} from "react-places-autocomplete";
import {db} from './Firebase';
import {useEffect} from 'react';
export default function Places() {
const [address, setAddress] = React.useState("");
const [coordinates, setCoordinates] = React.useState({
lat: null,
lng: null,
travelMode: "DRIVING"
});
const [destination, setDestinations] = React.useState([]);
let origins = [(coordinates.lat), (coordinates.lng)]
let travelMode = (coordinates.travelMode)
let destinations = destination.map(
position => {
return [(position.Latitude), (position.Longitude)]
}
)
useEffect(() => {
const unsub = db.collection('Location').onSnapshot (snapshot => {
const allPositions = snapshot.docs.map(doc => ({
id: doc.id,
... doc.data()
}));
setDestinations(allPositions);
})
return () => {
unsub();
};
}, [])
const handleSelect = async value => {
const results = await geocodeByAddress(value);
const latLng = await getLatLng(results[0]);
setAddress(value);
setCoordinates(latLng);
};
console.log (destinations)
return (
<div>
<PlacesAutocomplete
value={address}
onChange={setAddress}
onSelect={handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<p>Latitude: {coordinates.lat}</p>
<p>Longitude: {coordinates.lng}</p>
<input {...getInputProps({ placeholder: "Type address" })} />
<div>
{loading ? <div>...loading</div> : null}
{suggestions.map(suggestion => {
const style = {
backgroundColor: suggestion.active ? "#41b6e6" : "#fff"
};
return (
<div {...getSuggestionItemProps(suggestion, { style })}>
{suggestion.description}
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
</div>
);
}
我正在尝试计算一组坐标之间的距离,一对坐标是从坐标状态获取的,而其他坐标集是从目标状态获取后从一个数据库。我已经尝试将 React 库用于 Google 距离矩阵,但我在控制台中遇到了 CORS 块错误。
解决方案
您也可以尝试将距离矩阵服务用于距离矩阵的客户端应用程序。这是我为实现它而制作的示例代码。确保更改此行中的 API 密钥:
const API_KEY = "CHANGE_API_KEY_HERE";
下面是 distancematrix.js 文件的样子:
import React from "react";
import ReactDOM from 'react-dom';
const map;
var markers=[];
var infowindow;
const API_KEY = "CHANGE_API_KEY_HERE" ;
class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
origin: '',
dest: '',
distance: '',
duration: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.onScriptLoad = this.onScriptLoad.bind(this);
}
onScriptLoad() {
map = new window.google.maps.Map(document.getElementById(this.props.id), this.props.options);
this.props.onMapLoad(map)
}
componentDidMount() {
if (!window.google) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `https://maps.googleapis.com/maps/api/js?key=`+API_KEY+`&libraries=places,geometry`;
script.id = 'googleMaps';
script.async = true;
script.defer = true;
document.body.appendChild(script);
script.addEventListener('load', e => {
this.onScriptLoad()
})
}
else {
this.onScriptLoad()
}
var marker = new google.maps.Marker({
position: { lat: -25.344, lng: 131.036 },
map: map
});
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleBlur = (field) => (evt) => {
this.setState({
touched: { ...this.state.touched, [field]: true },
});
}
handleSubmit(event) {
this.getDistanceMatrix();
event.preventDefault();
}
geocodeAddress(addressResult) {
var geocoder = new google.maps.Geocoder();
console.log(addressResult[0]);
var address1 = addressResult[0];
geocoder.geocode({ 'address': address1 }, (results, status)=> {
if (status === 'OK') {
map.setCenter(results[0].geometry.location);
this.createMarker(results[0]);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
getDistanceMatrix(){
var service = new google.maps.DistanceMatrixService;
var orig = this.state.origin;
var dest = this.state.dest;
service.getDistanceMatrix({
origins: [orig],
destinations: [dest],
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, (response, status) => {
if (status !== 'OK') {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
this.geocodeAddress(origins);
this.geocodeAddress(destinations);
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
console.log(response);
for (var j = 0; j < results.length; j++) {
var element = results[j];
console.log(element);
var distanceString = element.distance.text;
var durationString = element.duration.text;
//add new value to the previousValue
this.setState ({
distance: distanceString
});
this.setState ({
duration: durationString
});
}
console.log(this.state.distance + ','+ this.state.duration)
}
}
});
}
createMarker(place) {
var image = {
url: 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png',
// This marker is 20 pixels wide by 32 pixels high.
size: new google.maps.Size(20, 32),
// The origin for this image is (0, 0).
origin: new google.maps.Point(0, 0),
// The anchor for this image is the base of the flagpole at (0, 32).
anchor: new google.maps.Point(0, 32)
};
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
title: place.formatted_address,
icon: image
});
markers.push(marker);
infowindow = new google.maps.InfoWindow();
var content =
'Formatted Address: ' + place.formatted_address +
'<br/>Location Type: ' + place.geometry.location_type +
'<br/>Address Type: ' + place.types +
'<br/>Place ID: ' + place.place_id;
marker.addListener('click', ()=>{
infowindow.setContent(content);
infowindow.open(map, marker);
});
}
render() {
return (
<div id="root">
<div className="map" id={this.props.id} />
<h1 htmlFor="input">Get Distance Matrix</h1>
<br/>
<input type="text" id="origin" name="origin"
placeholder="origin"
value={this.state.origin}
onChange={this.handleInputChange} />
<input type="text" id="dest" name="dest"
placeholder="destination"
value={this.state.dest}
onChange={this.handleInputChange} />
<br/><br/>
<button type="submit" color="primary" onClick={this.handleSubmit}>
Submit
</button><br/><br/>
<h1 htmlFor="input">Results </h1>
<label htmlFor="input"> Distance:{this.state.distance}</label><br/>
<label htmlFor="input"> Duration:{this.state.duration}</label>
</div>
)
}
}
export default Map;
推荐阅读
- javascript - 通过调用 REST 服务初始化全局变量 AngularJS 的问题
- javascript - 使用 array.reduce() 进行复杂的嵌套分组
- javascript - 如果我有一个键,则从 n 对象数组中获取一个对象
- amazon-web-services - CloudFormation:删除整个嵌套堆栈
- java - 当我使用带有继承的构造函数时出错
- python - 用于自定义 Python 设置以运行测试的 Docker 容器
- html - CSS:让类包含来自其他类的定义
- bash - 无法在 Bash 脚本的 cURL 命令中使用 PAT 访问 Azure DevOps API
- cypress - 使用 Cypress 存根“new Date()”
- c# - Unity如何从磁盘加载位图?