123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- import React from "react";
- import {
- Map,
- TileLayer,
- Marker,
- Popup,
- ZoomControl,
- ScaleControl,
- Polyline,
- // Tooltip,
- FeatureGroup
- } from "react-leaflet";
- //import L from "leaflet";
- import {EditControl} from "react-leaflet-draw";
- import "react-leaflet-fullscreen/dist/styles.css";
- import FullscreenControl from "react-leaflet-fullscreen";
- import "./../css/maps.css";
- import {calcDistance} from "./../helpers/distance";
- import {longitude, latitude, mapWidth, mapHeight} from "./../config/variables";
- import {Button} from "reactstrap";
- import PathButtons from "./../PathButtons";
- import {CustomInput, Input, Label, Row, Col, Container} from "reactstrap";
- import mapboxToken from "./../config/mapboxToken.js";
- import EvaluationTable from "./../EvaluationTable";
- const mapStyles = {
- "bright": "bright-v9",
- "satellite": "satellite-streets-v9",
- "light": "light-v9",
- "dark": "dark-v9",
- "basic": "basic-v9",
- "outdoor": "outdoors-v10"
- }
- //const customIcon = new L.Icon({
- // iconUrl: require("../images/marker_icon.png"),
- // iconSize: [24, 40],
- // iconAnchor: [12, 40],
- //});
- export default class Leaflet extends React.Component{
- constructor(props){
- super(props);
- this.state = {
- latitude: latitude,
- longitude: longitude,
- zoom: 15,
- path: [],
- distance: 0,
- drawMode: false,
- mapStyle: "bright-v9",
- shapeOptions: {
- color: "#000",
- opacity: 1,
- fillColor: "#000",
- fillOpacity: 0.2,
- weight: 2,
- smoothFactor: 20
- }
- }
- }
- updateState = (key, value) => {
- this.setState({[key]: value})
- this.getDistance()
- }
- addMarker = event => {
- if(!this.state.drawMode){
- console.log("addmarker")
- const { lat, lng } = event.latlng
- let pathCopy = this.state.path.slice();
- pathCopy.push([lat, lng]);
- this.setState({path: pathCopy})
- this.getDistance()
- }
- }
- updateMarker = (idx, event) => {
- let {lat, lng} = event.target.getLatLng();
- let pathCopy = this.state.path.slice();
- pathCopy[idx] = [lat, lng]
- this.setState({path: pathCopy})
- this.getDistance()
- }
- getDistance = () => {
- let dst = calcDistance(this.state.path)
- this.setState({distance: dst})
- }
- clearPath = () => {
- this.setState({path: [], distance: 0})
- }
- _editableFG = null
- _onChange = () => {
- // this._editableFG contains the edited geometry, which can be manipulated through the leaflet API
- const { onChange } = this.props;
- if (!this._editableFG || !onChange) {
- return;
- }
- const geojsonData = this._editableFG.leafletElement.toGeoJSON();
- onChange(geojsonData);
- }
- switchDrawMode = () => {
- this.setState({drawMode: !this.state.drawMode})
- }
- updateShapeOptions = (event, option) => {
- let value = event.target.value
- this.setState(prevState => ({
- shapeOptions: {
- ...prevState.shapeOptions,
- [option]: value
- }
- }))
- }
- selectMapStyle = (event) => {
- this.setState({mapStyle: mapStyles[event.target.value]})
- }
- render() {
- const position = [this.state.latitude, this.state.longitude]
- let testMarkers = this.props.markers
- let markers = <></>
- if (testMarkers){
- markers = this.props.markers.map((pos, idx) =>
- <Marker position={pos} key={idx}></Marker>
- )
- }else{
- markers = this.state.path.map((pos, idx) =>
- <Marker
- position={pos}
- draggable
- key={idx}
- riseOnHover={true}
- onDragend={(e) => this.updateMarker(idx, e)}
- // icon={customIcon}
- >
- {/*<Tooltip permanent>{idx}</Tooltip>*/}
- <Popup>
- {idx}
- </Popup>
- </Marker>
- )
- }
- return (
- <div>
- <div className="map">
- <Map
- center={position}
- zoom={this.state.zoom}
- zoomControl={false}
- style={{width: mapWidth, height: mapHeight}}
- onClick={this.addMarker}
- >
- <TileLayer
- maxZoom={30}
- attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
- url={"https://api.mapbox.com/styles/v1/mapbox/" + this.state.mapStyle + "/tiles/{z}/{x}/{y}?access_token=" + mapboxToken}
- />
- <FeatureGroup>
- <EditControl
- position="topright"
- onEdited={this._onEdited}
- onCreated={this._onCreated}
- onDeleted={this._onDeleted}
- onDrawStart={() => {this.setState({drawMode: true})}}
- draw={{
- marker: false,
- circlemarker: false,
- polyline: {shapeOptions: this.state.shapeOptions},
- polygon: {shapeOptions: this.state.shapeOptions},
- circle: {shapeOptions: this.state.shapeOptions},
- rectangle: {shapeOptions: this.state.shapeOptions},
- }}
- />
- </FeatureGroup>
- {markers}
- <Polyline color="grey" positions={this.state.path} />
- <ScaleControl position="bottomright"/>
- <ZoomControl position="bottomright" />
- <FullscreenControl position="topright"/>
- </Map>
- </div>
- <div className="mapInfo">
- <Button onClick={this.clearPath}>Clear path</Button>
- <Button onClick={this.getDistance}>Calculate Distance</Button>
- <Input type="select" name="selectMapStyle" id="selectMapStyle" onChange={this.selectMapStyle}>
- {Object.keys(mapStyles).map((key, idx) => (
- <option value={key} key={idx}>{key}</option>
- ))}
- </Input>
- <p>
- Distanz: {Math.round(this.state.distance*100)/100} km
- </p>
- <PathButtons updateState={this.updateState} path={this.state.path}/>
- <br/>
- <div>
- <Container>
- <Row>
- <Col xs="2">
- <Label for="drawMode">Draw</Label>
- </Col>
- <Col xs="2">
- <CustomInput type="switch" onChange={this.switchDrawMode} id="drawMode" name="drawMode"/>
- </Col>
- <Col xs="2">
- <Label for="weight">Weight</Label>
- </Col>
- <Col xs="6">
- <Input type="range" onChange={(e) => this.updateShapeOptions(e, "weight")} name="weight" id="weight" placeholder="weight" min="1" max="20" value={this.state.shapeOptions.weight}/>
- </Col>
- </Row>
- <Row>
- <Col xs="2">
- <Label for="colorPicker">Line Color</Label>
- </Col>
- <Col xs="2">
- <Input type="color" onChange={(e) => this.updateShapeOptions(e, "color")} name="color" id="colorPicker" placeholder="colorPicker"/>
- </Col>
- <Col xs="2">
- <Label for="opacity">Opacity</Label>
- </Col>
- <Col xs="6">
- <Input type="range" onChange={(e) => this.updateShapeOptions(e, "opacity")} name="opacity" id="opacity" placeholder="opacity" min="0" max="1" step="0.1" value={this.state.shapeOptions.opacity}/>
- </Col>
- </Row>
- <Row>
- <Col xs="2">
- <Label for="fillColorPicker">Fill Color</Label>
- </Col>
- <Col xs="2">
- <Input type="color" onChange={(e) => this.updateShapeOptions(e, "fillColor")} name="fillColorPicker" id="fillColorPicker" placeholder="fillColorPicker"/>
- </Col>
- <Col xs="2">
- <Label for="fillOpacity">Fill Opacity</Label>
- </Col>
- <Col xs="6">
- <Input type="range" onChange={(e) => this.updateShapeOptions(e, "fillOpacity")} name="fillOpacity" id="fillOpacity" placeholder="fillOpacity" min="0" max="1" step="0.1" value={this.state.shapeOptions.fillOpacity}/>
- </Col>
- </Row>
- </Container>
- </div>
- </div>
- <EvaluationTable mapId="leaflet"/>
- </div>
- );
- }
- }
|