Skip to content

Commit 790e4da

Browse files
committed
Added simplestyle-spec support to leaflet's GeoJSON
Minor css fixes Warning fixes
1 parent e32a23d commit 790e4da

File tree

6 files changed

+124
-32
lines changed

6 files changed

+124
-32
lines changed

src/common/utils/featuePopup.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
3+
import React from 'react';
4+
5+
const IgnoreFields = {
6+
title: true,
7+
description: true,
8+
"marker-size": true,
9+
"marker-symbol": true,
10+
"marker-color": true,
11+
stroke: true,
12+
"stroke-opacity": true,
13+
"stroke-width": true,
14+
fill: true,
15+
"fill-opacity": true
16+
};
17+
18+
export function popupFormat(properties) {
19+
const title = properties.title || "Feature";
20+
const description = properties.description || "";
21+
const rows = Object.keys(properties)
22+
.filter(key => !IgnoreFields.hasOwnProperty(key))
23+
.map(key => <tr><th>{key}</th><th>{properties[key]}</th></tr>)
24+
25+
return { title, description, rows };
26+
}

src/common/utils/tryParseFloat.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default function tryParseFloat(value, defaultValue) {
2+
if (typeof value === "number") {
3+
return value;
4+
} else if (typeof value === "string") {
5+
try {
6+
return parseFloat(value);
7+
} catch (e) {
8+
return defaultValue;
9+
}
10+
} else {
11+
return defaultValue;
12+
}
13+
}

src/components/Layers/Layers.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@
3131
display: block;
3232
}
3333

34-
.layers input[type="file"] {
35-
margin: 6px 8px;
36-
}
37-
3834
.layers .layer svg {
3935
fill: white;
4036
height: 1em;

src/components/Layers/Layers.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import axios from "axios";
77
import UploadFile from "./UploadFile";
88
import LayerTypes from '../../common/LayerTypes'
99

10-
import "leaflet-draw/dist/leaflet.draw.css";
1110
import CheckableItem from "./CheckableItem";
1211

1312
export default class Layers extends Component {

src/components/Layers/UploadFile.css

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
.upload-files {
1717
position: absolute;
18-
padding-top: 20px;
1918
left: 3px;
2019
right: 3px;
2120
top: 3px;
@@ -25,9 +24,6 @@
2524

2625
.upload-files input {
2726
display: inline-block;
28-
bottom: 0;
29-
right: 0;
30-
left: 20px;
3127
}
3228

3329
.upload-files .close-panel-button {
@@ -44,8 +40,7 @@
4440
display: inline-block;
4541
height: 25px;
4642
width: 25px;
47-
bottom: 7px;
48-
left: 7px;
43+
margin: 5px;
4944
fill: white;
5045
cursor: pointer;
5146
}

src/components/Map/Map.js

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@ import {
44
Map as LeafletMap,
55
TileLayer,
66
GeoJSON,
7-
Rectangle
7+
Rectangle,
8+
Popup
89
} from "react-leaflet";
910
import L from "leaflet";
1011
import { tileLayerTemplate } from "../../config";
1112
import LayerTypes from "../../common/LayerTypes";
13+
import { popupFormat } from "../../common/utils/featuePopup";
14+
import tryParseFloat from "../../common/utils/tryParseFloat";
15+
16+
const sizes = {
17+
small: 4,
18+
medium: 8,
19+
large: 12
20+
};
1221

1322
class MapComponent extends React.Component {
1423
static getDerivedStateFromProps(props, state) {
@@ -20,6 +29,7 @@ class MapComponent extends React.Component {
2029
}
2130

2231
state = {
32+
popup: null,
2333
lat: 31.84,
2434
lng: 34.84,
2535
zoom: 7,
@@ -41,19 +51,56 @@ class MapComponent extends React.Component {
4151
window.removeEventListener("resize", this.updateDimensions);
4252
}
4353

44-
pointToLayer(feature, latlng) {
45-
// renders our GeoJSON points as circle markers, rather than Leaflet's default image markers
46-
// parameters to style the GeoJSON markers
47-
const markerParams = {
48-
radius: 4,
49-
fillColor: "black",
50-
color: "#fff",
51-
weight: 0,
52-
fillOpacity: 1
53-
};
54-
55-
return L.circleMarker(latlng, markerParams);
56-
}
54+
onClick_Marker = e => {
55+
console.log(e);
56+
const fp = e.target.feature.properties || {};
57+
this.setState({
58+
popup: {
59+
id: Math.random()
60+
.toString(36)
61+
.substring(7),
62+
position: e.latlng,
63+
...popupFormat(fp)
64+
}
65+
});
66+
};
67+
68+
pointToLayer = (f, latlon) => L.circleMarker(latlon, {});
69+
70+
// Symology based on simplestyle-spec v1.1.0 of MapBox
71+
// https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0
72+
featureStyle = feature => {
73+
const fp = feature.properties || {};
74+
const fg = feature.geometry || {};
75+
if (fg.type === "MultiPoint" || fg.type === "Point") {
76+
const size = fp["marker-size"] || "medium";
77+
// const symbol = fp["marker-symbol"] ? "-" + fp["marker-symbol"] : "";
78+
const color = fp["marker-color"] || "#7e7e7e";
79+
return {
80+
radius: sizes[size],
81+
fillColor: color,
82+
weight: 0,
83+
fillOpacity: 1
84+
};
85+
} else {
86+
const stroke = fp["stroke"] || "#555555";
87+
const strokeOpacity = tryParseFloat(fp["stroke-opacity"], 1);
88+
const strokeWidth = tryParseFloat(fp["stroke-width"], 2);
89+
const fill = fp["fill"] || "#555555";
90+
const fillOpacity = tryParseFloat(fp["fill-opacity"], 0.6);
91+
return {
92+
color: stroke,
93+
weight: strokeWidth,
94+
opacity: strokeOpacity,
95+
fillColor: fill,
96+
fillOpacity
97+
};
98+
}
99+
};
100+
101+
onEachFeature = (feature, layer) => {
102+
layer.on("click", this.onClick_Marker);
103+
};
57104

58105
onMouseDown = ({ latlng }) => {
59106
if (this.props.isDrawingRectange) {
@@ -95,7 +142,7 @@ class MapComponent extends React.Component {
95142
render() {
96143
const position = [this.state.lat, this.state.lng];
97144
const { isDrawingRectange } = this.props;
98-
const { drawData } = this.state;
145+
const { drawData, popup } = this.state;
99146
const drawedRectangle =
100147
isDrawingRectange && drawData ? (
101148
<Rectangle
@@ -111,9 +158,10 @@ class MapComponent extends React.Component {
111158
);
112159
const rectangles = this.props.layers
113160
.filter(({ layerType }) => layerType === LayerTypes.BOUNDING_BOX)
114-
.map(({ data: { west, east, south, north } }) =>
115-
L.latLngBounds(L.latLng(south, west), L.latLng(north, east))
116-
);
161+
.map(({ id, data: { west, east, south, north } }) => ({
162+
bounds: L.latLngBounds(L.latLng(south, west), L.latLng(north, east)),
163+
id
164+
}));
117165
return (
118166
<div>
119167
<LeafletMap
@@ -130,12 +178,27 @@ class MapComponent extends React.Component {
130178
>
131179
<TileLayer url={tileLayerTemplate} />
132180
{geoJsons.map(layer => (
133-
<GeoJSON data={layer.data} pointToLayer={this.pointToLayer} />
181+
<GeoJSON
182+
key={layer.id}
183+
data={layer.data}
184+
style={this.featureStyle}
185+
pointToLayer={this.pointToLayer}
186+
onEachFeature={this.onEachFeature}
187+
/>
134188
))}
135-
{rectangles.map(rec => (
136-
<Rectangle bounds={rec} />
189+
{rectangles.map(({ id, bounds }) => (
190+
<Rectangle key={id} bounds={bounds} />
137191
))}
138192
{drawedRectangle}
193+
{popup ? (
194+
<Popup key={popup.id} position={popup.position}>
195+
<div>
196+
<h3>{popup.title}</h3>
197+
<p>{popup.description}</p>
198+
<table>{popup.rows}</table>
199+
</div>
200+
</Popup>
201+
) : null}
139202
</LeafletMap>
140203
</div>
141204
);

0 commit comments

Comments
 (0)