Skip to content
This repository has been archived by the owner on Jan 20, 2023. It is now read-only.

Commit

Permalink
#4/#5: publishing initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
grtjn committed Feb 4, 2020
1 parent e50aaf8 commit 97d2fc7
Show file tree
Hide file tree
Showing 30 changed files with 43,607 additions and 23 deletions.
3 changes: 0 additions & 3 deletions .gitignore
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Installation

`npm install grove-react-map-components`
`npm install @marklogic-community/grove-react-map-components`

## MapContext

Expand Down Expand Up @@ -68,4 +68,4 @@ This component shows a geospatial map using OpenLayers API. It displays the geos
>
> **lonLat** (default: `[-95.79, 34.48]`) - center of the map
>
> **zoom** (default: `4`) - zoom of the map
> **zoom** (default: `4`) - zoom of the map
149 changes: 149 additions & 0 deletions es/FeatureLayer.js
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;
}
124 changes: 124 additions & 0 deletions es/InfoWindow.js
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 })
)
);
}
Loading

0 comments on commit 97d2fc7

Please sign in to comment.