Leaflet.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import React from "react";
  2. import {
  3. Map,
  4. TileLayer,
  5. Marker,
  6. Popup,
  7. ZoomControl,
  8. Polyline,
  9. FeatureGroup
  10. } from "react-leaflet";
  11. import {EditControl} from "react-leaflet-draw";
  12. import L from "leaflet";
  13. import "./../css/maps.css";
  14. import {calcDistance} from "./../helpers/distance";
  15. import {longitude, latitude, mapWidth, mapHeight} from "./../config/variables";
  16. import {Button} from "reactstrap";
  17. import PathButtons from "./../PathButtons";
  18. export default class Leaflet extends React.Component{
  19. constructor(props){
  20. super(props);
  21. this.state = {
  22. latitude: latitude,
  23. longitude: longitude,
  24. zoom: 15,
  25. path: [],
  26. distance: 0,
  27. }
  28. }
  29. updateState = (key, value) => {
  30. this.setState({[key]: value})
  31. this.getDistance()
  32. }
  33. addMarker = event => {
  34. const { lat, lng } = event.latlng
  35. let pathCopy = this.state.path.slice();
  36. pathCopy.push([lat, lng]);
  37. this.setState({path: pathCopy})
  38. this.getDistance()
  39. }
  40. updateMarker = (idx, event) => {
  41. let {lat, lng} = event.target.getLatLng();
  42. let pathCopy = this.state.path.slice();
  43. pathCopy[idx] = [lat, lng]
  44. this.setState({path: pathCopy})
  45. this.getDistance()
  46. }
  47. getDistance = () => {
  48. let dst = calcDistance(this.state.path)
  49. this.setState({distance: dst})
  50. }
  51. clearPath = () => {
  52. this.setState({path: [], distance: 0})
  53. }
  54. _onEdited = (e) => {
  55. let numEdited = 0;
  56. e.layers.eachLayer( (layer) => {
  57. numEdited += 1;
  58. });
  59. this._onChange();
  60. }
  61. _onCreated = (e) => {
  62. let type = e.layerType;
  63. let layer = e.layer;
  64. // Do whatever else you need to. (save to db; etc)
  65. this._onChange();
  66. }
  67. _onDeleted = (e) => {
  68. let numDeleted = 0;
  69. e.layers.eachLayer( (layer) => {
  70. numDeleted += 1;
  71. });
  72. this._onChange();
  73. }
  74. _editableFG = null
  75. _onChange = () => {
  76. // this._editableFG contains the edited geometry, which can be manipulated through the leaflet API
  77. const { onChange } = this.props;
  78. if (!this._editableFG || !onChange) {
  79. return;
  80. }
  81. const geojsonData = this._editableFG.leafletElement.toGeoJSON();
  82. onChange(geojsonData);
  83. }
  84. render() {
  85. const position = [this.state.latitude, this.state.longitude]
  86. let testMarkers = this.props.markers
  87. let markers = <></>
  88. if (testMarkers){
  89. markers = this.props.markers.map((pos, idx) =>
  90. <Marker position={pos} key={idx}></Marker>
  91. )
  92. }else{
  93. markers = this.state.path.map((pos, idx) =>
  94. <Marker
  95. position={pos}
  96. draggable
  97. key={idx}
  98. onDragend={(e) => this.updateMarker(idx, e)}
  99. >
  100. <Popup>
  101. {idx}
  102. </Popup>
  103. </Marker>
  104. )
  105. }
  106. return (
  107. <div>
  108. <div className="map">
  109. <Map
  110. center={position}
  111. zoom={this.state.zoom}
  112. zoomControl={false}
  113. style={{width: mapWidth, height: mapHeight}}
  114. onClick={this.addMarker}
  115. >
  116. <TileLayer
  117. attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  118. url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
  119. />
  120. <FeatureGroup>
  121. <EditControl
  122. position='topright'
  123. onEdited={this._onEdited}
  124. onCreated={this._onCreated}
  125. onDeleted={this._onDeleted}
  126. draw={{rectangle: false}}
  127. />
  128. </FeatureGroup>
  129. {markers}
  130. <Polyline color="grey" positions={this.state.path} />
  131. <ZoomControl position="bottomright" />
  132. </Map>
  133. </div>
  134. <div className="mapInfo">
  135. <Button onClick={this.clearPath}>Clear path</Button>
  136. <Button onClick={this.getDistance}>Calculate Distance</Button>
  137. <p>
  138. Distanz: {Math.round(this.state.distance*100)/100} km
  139. </p>
  140. <PathButtons updateState={this.updateState} path={this.state.path}/>
  141. </div>
  142. </div>
  143. );
  144. }
  145. }