This repository has been archived by the owner on Jan 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
43,607 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,5 @@ | ||
/coverage | ||
/demo/dist | ||
/es | ||
/lib | ||
/node_modules | ||
/umd | ||
npm-debug.log* | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
|
||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } | ||
|
||
import React, { useEffect, useContext, useRef } from "react"; | ||
import Feature from "ol/Feature"; | ||
import { Point } from "ol/geom"; | ||
import { fromLonLat } from "ol/proj"; | ||
import { Circle as CircleStyle, Fill, Stroke, Style, Text } from "ol/style.js"; | ||
import { Vector as VectorLayer } from "ol/layer.js"; | ||
import { Vector as VectorSource, Cluster as ClusterSource } from "ol/source.js"; | ||
import { MapContext } from "./MapContext"; | ||
|
||
function getPointLongLat(point) { | ||
var geo = point.geometry || point.location; | ||
var latlng = geo.coordinates || [geo.long || geo.longitude || 0, geo.lat || geo.latitude || 0]; | ||
return latlng; | ||
} | ||
|
||
export default function FeatureLayer(props) { | ||
var context = useContext(MapContext); | ||
var styles = useRef({}); | ||
var layer = useRef(null); | ||
var source = useRef(null); | ||
|
||
useEffect(function () { | ||
var styleMap = {}; | ||
var config = props.styleMap; | ||
Object.keys(config).forEach(function (key) { | ||
var opts = _extends({}, config[key]); | ||
if (opts.circle) { | ||
var _opts$circle = opts.circle, | ||
fill = _opts$circle.fill, | ||
stroke = _opts$circle.stroke, | ||
circle = _objectWithoutProperties(_opts$circle, ["fill", "stroke"]); | ||
// TODO: might be able to genericize this | ||
|
||
|
||
if (fill) { | ||
circle.fill = new Fill(fill); | ||
} | ||
if (stroke) { | ||
circle.stroke = new Stroke(stroke); | ||
} | ||
opts.image = new CircleStyle(circle); | ||
console.log("new circle style", opts, config); | ||
} | ||
if (opts.text) { | ||
var _opts$text = opts.text, | ||
_fill = _opts$text.fill, | ||
text = _objectWithoutProperties(_opts$text, ["fill"]); | ||
|
||
if (_fill) { | ||
text.fill = new Fill(_fill); | ||
} | ||
opts.text = new Text(text); | ||
} | ||
console.log("creating new style in stylemap", key, opts); | ||
styleMap[key] = new Style(opts); | ||
}); | ||
|
||
console.log("returning stylemap ", styleMap, config); | ||
styles.current = styleMap; | ||
}, [props.styleMap]); | ||
|
||
useEffect(function () { | ||
if (context.map) { | ||
console.log("creating new FeatureLayer source for layer name", props.layerName); | ||
source.current = new VectorSource(); | ||
|
||
var clusterSource = void 0; | ||
|
||
if (props.cluster) { | ||
clusterSource = new ClusterSource(_extends({}, props.cluster, { | ||
source: source.current | ||
})); | ||
} | ||
|
||
layer.current = new VectorLayer({ | ||
projection: props.projection || "EPSG:4326", | ||
source: clusterSource || source.current, | ||
style: function style(feature) { | ||
var style = void 0; | ||
if (feature.values_.features) { | ||
var type = feature.values_.features[0].get("type"); | ||
style = styles.current[type]; | ||
if (style.getText()) { | ||
style.getText().setText("" + feature.values_.features.length); | ||
} | ||
} else { | ||
var myfeature = feature.values_; | ||
style = styles.current[myfeature.type]; | ||
if (style.getText()) { | ||
style.getText().setText(myfeature.data.properties.name); | ||
} | ||
} | ||
return style; | ||
} | ||
}); | ||
|
||
context.map.addLayer(layer.current); | ||
|
||
if (props.features) { | ||
buildFeatures(); | ||
} | ||
|
||
return function () { | ||
context.map.removeLayer(layer.current); | ||
}; | ||
} | ||
}, [context.map]); | ||
|
||
function buildFeatures() { | ||
console.log("building features for FeatureLayer %s with ", props.layerName, props.features); | ||
source.current.addFeatures(props.features.map(function (point) { | ||
return new Feature({ | ||
featureType: props.featureType || "point", | ||
type: point.type, | ||
data: point, | ||
geometry: new Point(fromLonLat(getPointLongLat(point))) | ||
}); | ||
})); | ||
|
||
if (props.fit) { | ||
context.map.getView().fit(source.current.getExtent(), context.map.getSize()); | ||
} | ||
} | ||
|
||
useEffect(function () { | ||
if (source.current && context.map) { | ||
buildFeatures(); | ||
|
||
// clear the features on change | ||
return function () { | ||
if (source.current) { | ||
source.current.clear(); | ||
} | ||
}; | ||
} | ||
}, [props.features]); | ||
|
||
useEffect(function () { | ||
if (layer.current) { | ||
layer.current.setVisible(!props.hidden); | ||
} | ||
}, [props.hidden]); | ||
|
||
return null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import React, { useEffect, useContext, useState, useRef } from "react"; | ||
import Overlay from "ol/Overlay.js"; | ||
import { Select } from "ol/interaction"; | ||
import { click, pointerMove } from "ol/events/condition.js"; | ||
import { MapContext } from "./MapContext"; | ||
import { fromLonLat } from "ol/proj"; | ||
|
||
export default function InfoWindow(_ref) { | ||
var _ref$interaction = _ref.interaction, | ||
interaction = _ref$interaction === undefined ? "singleclick" : _ref$interaction, | ||
_ref$autoPan = _ref.autoPan, | ||
autoPan = _ref$autoPan === undefined ? false : _ref$autoPan, | ||
_ref$ignoreTypes = _ref.ignoreTypes, | ||
ignoreTypes = _ref$ignoreTypes === undefined ? [] : _ref$ignoreTypes, | ||
_ref$renderer = _ref.renderer, | ||
renderer = _ref$renderer === undefined ? function () {} : _ref$renderer; | ||
|
||
var context = useContext(MapContext); | ||
var overlayRef = useRef(null); | ||
var layer = useRef(null); | ||
|
||
var _useState = useState([]), | ||
features = _useState[0], | ||
setFeatures = _useState[1]; | ||
|
||
var _useState2 = useState(null), | ||
selectedFeature = _useState2[0], | ||
selectFeature = _useState2[1]; | ||
|
||
var select = useRef(false); | ||
|
||
function showInfoWindow(evt) { | ||
if (evt.selected.length > 0) { | ||
var feature = evt.selected[0]; | ||
// we only work on clustered nodes for now | ||
if (feature.values_.hasOwnProperty("features")) { | ||
setFeatures(feature.values_.features); | ||
selectFeature(feature.values_.features[0].values_.data); | ||
layer.current.setPosition(feature.getGeometry().getCoordinates()); | ||
} else if (Array.isArray(feature.values_.data)) { | ||
selectFeature(feature.values_.data); | ||
layer.current.setPosition(fromLonLat(feature.values_.data[feature.values_.data.length / 2])); | ||
} else { | ||
selectFeature(feature.values_.data); | ||
layer.current.setPosition(feature.getGeometry().getCoordinates()); | ||
} | ||
} else { | ||
layer.current.setPosition(undefined); | ||
select.current.getFeatures().clear(); | ||
} | ||
} | ||
|
||
function getConditions() { | ||
switch (interaction) { | ||
case "hover": | ||
return { condition: pointerMove }; | ||
case "click": | ||
return { condition: click }; | ||
default: | ||
return null; | ||
} | ||
} | ||
|
||
// setup the interaction only once, whenever the map changes | ||
useEffect(function () { | ||
if (context.map) { | ||
// setup the interaction | ||
var config = getConditions(); | ||
config.filter = function (feature) { | ||
// use our internal setting of featuretype to ignore | ||
var featuretype = feature.values_.featureType; | ||
if (feature.values_.hasOwnProperty("features")) { | ||
if (feature.values_.features.length === 1) { | ||
featuretype = feature.values_.features[0].values_.featureType; | ||
} else { | ||
featuretype = "cluster"; | ||
} | ||
} | ||
var show = !ignoreTypes.includes(featuretype); | ||
return show; | ||
}; | ||
select.current = new Select(config); | ||
context.map.addInteraction(select.current); | ||
console.log("InfoWindow adding hover interaction"); | ||
select.current.on("select", showInfoWindow); | ||
return function () { | ||
select.current.un("select", showInfoWindow); | ||
context.map.removeInteraction(select.current); | ||
}; | ||
} | ||
}, [context.map]); | ||
|
||
// add the rendered component | ||
useEffect(function () { | ||
if (context.map) { | ||
console.log("overlayRefs.current", overlayRef.current); | ||
layer.current = new Overlay({ | ||
element: overlayRef.current.querySelector(".grove-info-window"), | ||
autoPan: !!autoPan, | ||
autoPanAnimation: { | ||
duration: autoPan | ||
} | ||
}); | ||
|
||
console.log("InfoWindow adding overlay layer"); | ||
context.map.addOverlay(layer.current); | ||
|
||
return function () { | ||
console.log("InfoWindow cleaning up overlay layer effect"); | ||
context.map.getOverlays().remove(layer.current); | ||
}; | ||
} | ||
}, [context.map]); | ||
|
||
return React.createElement( | ||
"div", | ||
{ ref: overlayRef }, | ||
React.createElement( | ||
"div", | ||
{ className: "ol-popup ol-popup-layer grove-info-window" }, | ||
renderer({ feature: selectedFeature, features: features }) | ||
) | ||
); | ||
} |
Oops, something went wrong.