123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- import React from "react";
- import ReactMapGL from "react-map-gl";
- import {
- Marker,
- NavigationControl,
- FullscreenControl,
- ScaleControl,
- GeolocateControl,
- Layer,
- Source,
- } from "react-map-gl";
- import "./../css/maps.css";
- import mapboxToken from "./../config/mapboxToken.js";
- import {calcDistance} from "./../helpers/distance";
- import {longitude, latitude, mapWidth, mapHeight, markerIcon} from "./../config/variables";
- import {Button, Input, Label, Row, Col, Container} from "reactstrap";
- import {getRoute} from "./../helpers/mapboxHelper";
- import PathButtons from "./../PathButtons";
- import {
- Editor,
- EditingMode,
- DrawLineStringMode,
- DrawPolygonMode,
- } from "react-map-gl-draw";
- import EvaluationTable from "./../EvaluationTable";
- const drawModes = [
- {id: "drawPolyline", text: "Draw Polyline", handler: DrawLineStringMode},
- {id: "drawPolygon", text: "Draw Polygon", handler: DrawPolygonMode},
- {id: "editing", text: "Edit Feature", handler: EditingMode},
- ];
- export default class MapGL extends React.Component{
- constructor(props){
- super(props);
- this.state = {
- viewport: {
- width: mapWidth,
- height: mapHeight,
- latitude: latitude,
- longitude: longitude,
- zoom: 14,
- bearing: 0,
- pitch: 0
- },
- path: [[longitude, latitude]],
- distance: 0,
- drawModeId: null,
- drawModeHandler: null,
- color: "rgb(189,189,189)",
- strokeDash: "4,2",
- strokeWidth: 2,
- fill: "rgb(189,189,189)",
- fillOpacity: 0.2
- }
- this.getRoute = getRoute.bind(this)
- }
- updateState = (key, value) => {
- this.setState({[key]: value})
- this.getDistance()
- }
- addMarker = event => {
- if (this.state.drawModeHandler===null){
- const lng = event.lngLat[0]
- const lat = event.lngLat[1]
- this.getRoute(lng, lat);
- }
- }
- updateMarker = (idx, event) => {
- const lng = event.lngLat[0]
- const lat = event.lngLat[1]
- let pathCopy = this.state.path.slice();
- pathCopy[idx] = [lng, lat]
- this.setState({path: pathCopy})
- this.getDistance()
- }
- getDistance = () => {
- let dst = calcDistance(this.state.path)
- this.setState({distance: dst})
- }
- clearPath = () => {
- this.setState({path: [], distance: 0})
- }
- switchDrawMode = (event) => {
- const modeId = event.target.value===this.state.drawModeId ? null:event.target.value;
- const mode = drawModes.find((m) => m.id===modeId);
- const modeHandler = mode ? new mode.handler() : null;
- this.setState({"drawModeid": modeId, "drawModeHandler": modeHandler});
- };
- drawToolbar = () => {
- return (
- <div style={{maxWidth: "320px"}}>
- <Input type="select" onChange={this.switchDrawMode}>
- <option value="">-</option>
- {drawModes.map((mode) => (
- <option key={mode.id} value={mode.id}>
- {mode.text}
- </option>
- ))}
- </Input>
- </div>
- )
- }
- render() {
- let testMarkers = this.props.markers
- let markers = <></>
- if (testMarkers){
- markers = testMarkers.map((pos, idx) => {
- return(
- <Marker
- longitude={pos[0]}
- latitude={pos[1]}
- captureClick={false}
- offsetTop={-20}
- offsetLeft={-8}
- key={idx}
- >
- <svg height={20} viewBox="0 0 24 24" style={{fill: "#343a40", stroke: "none", position: "absolute", top: "3px"}}>
- <path d={markerIcon} />
- </svg>
- </Marker>
- )}
- )
- }else{
- markers = this.state.path.map((pos, idx) => {
- return(
- <Marker
- longitude={pos[0]}
- latitude={pos[1]}
- captureClick={false}
- draggable={true}
- offsetTop={-20}
- offsetLeft={-8}
- key={idx}
- onDragEnd={(e) => this.updateMarker(idx, e)}
- >
- <svg height={20} viewBox="0 0 24 24" style={{fill: "#343a40", stroke: "none", position: "absolute", top: "3px"}}>
- {(idx===0 || idx===this.state.path.length-1 ?
- (<path d={markerIcon} /> )
- : (<circle cx="10" cy="19" r="5"/>)
- )}
- </svg>
- </Marker>
- )
- })
- }
- return (
- <div>
- <div className="map">
- <ReactMapGL
- {...this.state.viewport}
- onViewportChange={(viewport) => this.setState({viewport})}
- mapboxApiAccessToken={mapboxToken}
- mapStyle="mapbox://styles/mapbox/streets-v11"
- onClick={this.addMarker}
- >
- <Source
- id="routeSource"
- type="geojson"
- data={{type: "LineString", coordinates: this.state.path}}
- >
- <Layer
- source="routeSource"
- id="route"
- type="line"
- paint={{"line-color": "#888", "line-width": 3}}
- layout= {{"line-join": "round", "line-cap": "round"}}
- />
- </Source>
- {markers}
- <Editor
- clickRadius={12}
- mode={this.state.drawModeHandler}
- onSelect={(_) => {console.log("on select")}}
- featureStyle={({ feature, state }) => {
- return {
- stroke: this.state.color,
- strokeDasharray: this.state.strokeDash,
- strokeWidth: this.state.strokeWidth,
- fill: this.state.fill,
- fillOpacity: this.state.fillOpacity
- }
- }}
- />
- <div className="controllers">
- <GeolocateControl/>
- <FullscreenControl/>
- <NavigationControl/>
- <ScaleControl/>
- </div>
- </ReactMapGL>
- </div>
- <div className="mapInfo">
- <Button onClick={this.clearPath}>Clear path</Button>
- <Button onClick={this.getDistance}>Calculate Distance</Button>
- <p>
- Distanz: {Math.round(this.state.distance*100)/100} km
- </p>
- <PathButtons updateState={this.updateState} path={this.state.path} switchLatLng={true}/>
- <br/>
- <div>
- <Container>
- <Row>
- <Col xs="4">
- {this.drawToolbar()}
- </Col>
- <Col xs="2">
- <Label for="colorPicker">Stroke Dash</Label>
- </Col>
- <Col xs="6">
- <Input type="text" onChange={(e) => this.setState({"strokeDash": e.target.value})} name="strokeDash" id="strokeDash" placeholder="4,2"/>
- </Col>
- </Row>
- <Row>
- <Col xs="2">
- <Label for="colorPicker">Line Color</Label>
- </Col>
- <Col xs="2">
- <Input type="color" onChange={(e) => this.setState({"color": e.target.value})} name="color" id="colorPicker" placeholder="colorPicker"/>
- </Col>
- <Col xs="2">
- <Label for="weight">Weight</Label>
- </Col>
- <Col xs="6">
- <Input type="range" onChange={(e) => this.setState({"strokeWidth": e.target.value})} name="weight" id="weight" placeholder="weight" min="1" max="20" value={this.state.weight}/>
- </Col>
- </Row>
- <Row>
- <Col xs="2">
- <Label for="fillColorPicker">Fill Color</Label>
- </Col>
- <Col xs="2">
- <Input type="color" onChange={(e) => this.setState({"fill": e.target.value})} 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.setState({"fillOpacity": e.target.value})} name="fillOpacity" id="fillOpacity" placeholder="fillOpacity" min="0" max="1" step="0.1" value={this.state.fillOpacity}/>
- </Col>
- </Row>
- </Container>
- </div>
- </div>
- <EvaluationTable mapId="mapgl"/>
- </div>
- );
- }
- }
|