Google.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import React from "react";
  2. import GoogleMapReact from "google-map-react";
  3. import "./../css/maps.css";
  4. import apiKey from './../config/googleApiKey.js';
  5. import {calcDistance} from './../helpers/distance';
  6. import {longitude, latitude, mapWidth, mapHeight, markerIcon, testPath} from "./../config/variables";
  7. import {Button} from "reactstrap";
  8. import PathButtons from "./../PathButtons";
  9. import EvaluationTable from "./../EvaluationTable";
  10. const svgStyle = {
  11. top: "-20",
  12. left: "-8",
  13. position: "absolute"
  14. };
  15. const Marker = ({ text }) =>
  16. <div>
  17. <svg height={20} viewBox="0 0 24 24" style={svgStyle}>
  18. <path d={markerIcon}/>
  19. </svg>
  20. <p>{text}</p>
  21. </div>;
  22. let pathPolyLines = [];
  23. export default class Google extends React.Component{
  24. constructor(props){
  25. super(props);
  26. this.state = {
  27. latitude: latitude,
  28. longitude: longitude,
  29. zoom: 15,
  30. distance: 0,
  31. path: testPath,
  32. draggable: true
  33. }
  34. }
  35. componentDidUpdate(){
  36. this.drawPath()
  37. }
  38. updateState = (key, value) => {
  39. this.setState({[key]: value})
  40. this.getDistance()
  41. }
  42. getRoute = (lng, lat) => {
  43. let pathCopy = this.state.path.slice();
  44. var end = [lat, lng];
  45. if (this.state.path.length < 1){
  46. pathCopy.push(end)
  47. this.setState({path: pathCopy})
  48. } else {
  49. console.log("requesting the directions..")
  50. var start = this.state.path[this.state.path.length-1];
  51. var proxyurl = "https://cors-anywhere.herokuapp.com/";
  52. var baseUrl = "https://maps.googleapis.com/maps/api/directions/json?origin="
  53. var url = baseUrl + start[0] + "," + start[1] + "&destination=" + end[0] + "," + end[1] + "&key=" + apiKey;
  54. var reqOptions = {
  55. method:'GET',
  56. mode: 'cors',
  57. headers:{
  58. 'Access-Control-Allow-Origin':'*'
  59. },
  60. }
  61. fetch(proxyurl + url, reqOptions)
  62. .then(response => response.json())
  63. .then(data => {
  64. let routes = data.routes
  65. if(routes.length > 0){
  66. let steps = routes[0].legs[0].steps
  67. steps.forEach(step => {
  68. pathCopy.push([step.end_location.lat, step.end_location.lng])
  69. })
  70. } else{
  71. pathCopy.push(end)
  72. }
  73. this.setState({path: pathCopy})
  74. this.getDistance()
  75. })
  76. .catch((error) =>{
  77. console.error(error);
  78. });
  79. }
  80. }
  81. onMarkerInteraction = (childKey, childProps, mouse) => {
  82. this.setState({draggable: false});
  83. }
  84. addMarker = (event) => {
  85. const lng = event.lng
  86. const lat = event.lat
  87. let pathCopy = this.state.path.slice();
  88. pathCopy.push([lat, lng])
  89. this.setState({path: pathCopy})
  90. // this.getRoute(lng, lat);
  91. this.getDistance()
  92. }
  93. updateMarker = (childKey, childProps, mouse) => {
  94. const lng = mouse.lng
  95. const lat = mouse.lat
  96. console.log("new position (marker", childKey, "):", lat, lng)
  97. let pathCopy = this.state.path.slice();
  98. pathCopy[childKey] = [lat, lng]
  99. this.setState({path: pathCopy, draggable: true})
  100. this.getDistance()
  101. pathPolyLines.forEach(polyline => {
  102. polyline.setMap(null);
  103. })
  104. this.drawPath();
  105. }
  106. getDistance = () => {
  107. let dst = calcDistance(this.state.path)
  108. this.setState({distance: dst})
  109. }
  110. clearPath = () => {
  111. this.setState({path: [], distance: 0})
  112. pathPolyLines.forEach(polyline => {
  113. polyline.setMap(null);
  114. })
  115. }
  116. drawPath = () => {
  117. if (!this.props.markers){
  118. let path = this.state.path.map(p => {
  119. return {lat: p[0], lng: p[1]}
  120. })
  121. let map = this.state.map
  122. let maps = this.state.maps
  123. pathPolyLines.push(new maps.Polyline({
  124. path: path,
  125. geodesic: true,
  126. strokeColor: "#212529",
  127. strokeOpacity: 1.0,
  128. strokeWeight: 4,
  129. map,
  130. }));
  131. }
  132. }
  133. handleApiLoaded = (map, maps) => {
  134. // map.setMapTypeId("satellite");
  135. this.setState({map: map, maps: maps})
  136. }
  137. render() {
  138. const position = [this.state.latitude, this.state.longitude]
  139. let testMarkers = this.props.markers
  140. let markers = <></>
  141. if (testMarkers){
  142. markers = this.props.markers.map((pos, idx) =>
  143. <Marker
  144. lat={pos[0]}
  145. lng={pos[1]}
  146. key={idx}
  147. />
  148. )
  149. }else{
  150. markers = this.state.path.map((pos, idx) =>
  151. <Marker
  152. lat={pos[0]}
  153. lng={pos[1]}
  154. text={idx}
  155. key={idx}
  156. draggable={true}
  157. onDragEnd={(e) => this.updateMarker(idx, e)}
  158. />
  159. )}
  160. return (
  161. <div>
  162. <div className="map" style={{height: mapHeight, width: mapWidth}}>
  163. <GoogleMapReact
  164. bootstrapURLKeys={{ key: apiKey }}
  165. defaultCenter={position}
  166. defaultZoom={this.state.zoom}
  167. yesIWantToUseGoogleMapApiInternals
  168. layerTypes={['TrafficLayer', 'TransitLayer']}
  169. onClick={(e, c) => this.addMarker(e, c)}
  170. draggable={this.state.draggable}
  171. onChildMouseDown={this.onMarkerInteraction}
  172. onChildMouseUp={this.updateMarker}
  173. onGoogleApiLoaded={({map, maps}) => this.handleApiLoaded(map, maps)}
  174. >
  175. {markers}
  176. </GoogleMapReact>
  177. </div>
  178. <div className="mapInfo">
  179. <Button onClick={this.clearPath}>Clear path</Button>
  180. <Button onClick={this.getDistance}>Calculate Distance</Button>
  181. <p>
  182. Distanz: {Math.round(this.state.distance*100)/100} km
  183. </p>
  184. <PathButtons updateState={this.updateState} path={this.state.path}/>
  185. </div>
  186. <EvaluationTable mapId="google"/>
  187. </div>
  188. );
  189. }
  190. }