Skip to content

Commit

Permalink
Fixed extra features for openlayers (#1793)
Browse files Browse the repository at this point in the history
* Fixed extra features for openlayers

* added test

* fixed test
  • Loading branch information
MV88 authored and mbarto committed May 9, 2017
1 parent ce68cd8 commit cf91f48
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 88 deletions.
21 changes: 13 additions & 8 deletions web/client/components/map/openlayers/Feature.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2015, GeoSolutions Sas.
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
Expand All @@ -14,6 +14,7 @@ let Feature = React.createClass({
propTypes: {
type: React.PropTypes.string,
properties: React.PropTypes.object,
crs: React.PropTypes.string,
container: React.PropTypes.object, // TODO it must be a ol.layer.vector (maybe pass the source is more correct here?)
geometry: React.PropTypes.object, // TODO check for geojson format for geometry
msId: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
Expand All @@ -29,8 +30,12 @@ let Feature = React.createClass({
const geometry = this.props.geometry && this.props.geometry.coordinates;

if (this.props.container && geometry) {
this._feature = format.readFeatures({type: this.props.type, properties: this.props.properties, geometry: this.props.geometry, id: this.props.msId});
this._feature.forEach((f) => f.getGeometry().transform(this.props.featuresCrs, 'EPSG:3857'));
this._feature = format.readFeatures({
type: this.props.type,
properties: this.props.properties,
geometry: this.props.geometry,
id: this.props.msId});
this._feature.forEach((f) => f.getGeometry().transform(this.props.featuresCrs, this.props.crs || 'EPSG:3857'));
this.props.container.getSource().addFeatures(this._feature);
}
},
Expand All @@ -42,7 +47,7 @@ let Feature = React.createClass({

if (newProps.container && geometry) {
this._feature = format.readFeatures({type: newProps.type, properties: newProps.properties, geometry: newProps.geometry, id: this.props.msId});
this._feature.forEach((f) => f.getGeometry().transform(newProps.featuresCrs, 'EPSG:3857'));
this._feature.forEach((f) => f.getGeometry().transform(newProps.featuresCrs, this.props.crs || 'EPSG:3857'));
newProps.container.getSource().addFeatures(this._feature);
}
}
Expand All @@ -61,11 +66,11 @@ let Feature = React.createClass({
if (Array.isArray(this._feature)) {
const layersSource = this.props.container.getSource();
this._feature.map((feature) => {
let fetureId = feature.getId();
if (fetureId === undefined) {
let featureId = feature.getId();
if (featureId === undefined) {
layersSource.removeFeature(feature);
}else {
layersSource.removeFeature(layersSource.getFeatureById(fetureId));
layersSource.removeFeature(layersSource.getFeatureById(featureId));
}
});
} else {
Expand Down
106 changes: 106 additions & 0 deletions web/client/components/map/openlayers/__tests__/Feature-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const ReactDOM = require('react-dom');
const ol = require('openlayers');
const Feature = require('../Feature.jsx');
const expect = require('expect');
require('../../../../utils/openlayers/Layers');
require('../plugins/VectorLayer');

describe('Test Feature', () => {
document.body.innerHTML = '<div id="map"></div>';
let map;

beforeEach((done) => {
document.body.innerHTML = '<div id="map"></div><div id="container"></div>';
map = new ol.Map({
layers: [
],
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 5
})
});
setTimeout(done);
});

afterEach((done) => {
map.setTarget(null);
document.body.innerHTML = '';
setTimeout(done);
});

it('adding a feature to a vector layer', () => {
var options = {
crs: 'EPSG:4326',
features: {
type: 'FeatureCollection',
crs: {
'type': 'name',
'properties': {
'name': 'EPSG:4326'
}
},
features: [
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[
[13, 43],
[15, 43],
[15, 44],
[13, 44]
]]
},
properties: {
'name': "some name"
}
}
]
}
};
const source = new ol.source.Vector({
features: []
});
const msId = "some value";
let container = new ol.layer.Vector({
msId,
source: source,
visible: true,
zIndex: 1
});
const geometry = options.features.features[0].geometry;
const type = options.features.features[0].type;
const properties = options.features.features[0].properties;

// create layers
let layer = ReactDOM.render(
<Feature type="vector"
options={options}
geometry={geometry}
type={type}
properties={properties}
msId={msId}
container={container}
featuresCrs={"EPSG:4326"}
crs={"EPSG:4326"}
/>, document.getElementById("container"));

expect(layer).toExist();
// count layers
expect(container.getSource().getFeatures().length === 1 );
});
});
152 changes: 74 additions & 78 deletions web/client/components/map/openlayers/plugins/VectorLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var Layers = require('../../../../utils/openlayers/Layers');
var markerIcon = require('../img/marker-icon.png');
var markerShadow = require('../img/marker-shadow.png');
var ol = require('openlayers');
const {isEqual} = require('lodash');

const assign = require('object-assign');

Expand Down Expand Up @@ -104,106 +105,101 @@ var styleFunction = function(feature) {
return defaultStyles[feature.getGeometry().getType()];
};

Layers.registerType('vector', {
create: (options) => {
let features;
let featuresCrs = options.featuresCrs || 'EPSG:4326';
let layerCrs = options.crs || 'EPSG:3857';
if (options.features) {
let featureCollection = options.features;
if (Array.isArray(options.features)) {
featureCollection = { "type": "FeatureCollection", features: featureCollection};
}
features = (new ol.format.GeoJSON()).readFeatures(featureCollection);
if (featuresCrs !== layerCrs) {
features.forEach((f) => f.getGeometry().transform(featuresCrs, layerCrs));
}
}
function getStyle(options) {
let style = options.nativeStyle;
if (!style && options.style) {
style = {
stroke: new ol.style.Stroke( options.style.stroke ? options.style.stroke : {
color: 'blue',
width: 1
}),
fill: new ol.style.Fill(options.style.fill ? options.style.fill : {
color: 'blue'
})
};

const source = new ol.source.Vector({
features: features
});

let style = options.nativeStyle;
if (!style && options.style) {
if (options.style.type === "Point") {
style = {
stroke: new ol.style.Stroke( options.style.stroke ? options.style.stroke : {
color: 'blue',
width: 1
}),
fill: new ol.style.Fill(options.style.fill ? options.style.fill : {
color: 'blue'
})
image: new ol.style.Circle(assign({}, style, {radius: options.style.radius || 5}))
};
}

if (options.style.type === "Point") {
style = {
image: new ol.style.Circle(assign({}, style, {radius: options.style.radius || 5}))
};
}

if (options.style.iconUrl ) {
let markerStyle = [new ol.style.Style({
if (options.style.iconUrl ) {
let markerStyle = [new ol.style.Style({
image: new ol.style.Icon(({
anchor: options.iconAnchor || [0.5, 1],
anchorXUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
anchorYUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
src: options.style.iconUrl
}))
})];
if (options.style.shadowUrl) {
markerStyle = [new ol.style.Style({
image: new ol.style.Icon(({
anchor: options.iconAnchor || [0.5, 1],
anchorXUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
anchorYUnits: ( options.iconAnchor || options.iconAnchor === 0) ? 'pixels' : 'fraction',
src: options.style.iconUrl
}))
})];
if (options.style.shadowUrl) {
markerStyle = [new ol.style.Style({
image: new ol.style.Icon(({
anchor: [12, 41],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: options.style.shadowUrl || markerShadow
}))
}), markerStyle [0]];
anchor: [12, 41],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: options.style.shadowUrl || markerShadow
}))
}), markerStyle [0]];
}
style = (feature) => {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return markerStyle;
default:
return styleFunction(feature);
}
style = (feature) => {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return markerStyle;
default:
return styleFunction(feature);
}
};
} else {
style = new ol.style.Style(style);
};
} else {
style = new ol.style.Style(style);
}
}
return (options.styleName && !options.overrideOLStyle) ? (feature) => {
if (options.styleName === "marker") {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return defaultStyles.marker;
default:
break;
}
}
return defaultStyles[options.styleName];
} : style || styleFunction;
}
Layers.registerType('vector', {
create: (options) => {
let features = [];

const source = new ol.source.Vector({
features: features
});

const style = getStyle(options);

return new ol.layer.Vector({
msId: options.id,
source: source,
visible: options.visibility !== false,
zIndex: options.zIndex,
style: (options.styleName && !options.overrideOLStyle) ? (feature) => {
if (options.styleName === "marker") {
const type = feature.getGeometry().getType();
switch (type) {
case "Point":
case "MultiPoint":
return defaultStyles.marker;
default:
break;
}
}
return defaultStyles[options.styleName];
} : style || styleFunction
style
});
},
update: (layer, newOptions, oldOptions) => {
const oldCrs = oldOptions.crs || 'EPSG:3857';
const newCrs = newOptions.crs || 'EPSG:3857';
const oldCrs = oldOptions.crs || oldOptions.srs || 'EPSG:3857';
const newCrs = newOptions.crs || newOptions.srs || 'EPSG:3857';
if (newCrs !== oldCrs) {
layer.getSource().forEachFeature((f) => {
f.getGeometry().transform(oldCrs, newCrs);
});
}
if (!isEqual(oldOptions.style, newOptions.style)) {
layer.setStyle(getStyle(newOptions));
}
},
render: () => {
return null;
Expand Down
6 changes: 4 additions & 2 deletions web/client/plugins/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ const MapPlugin = React.createClass({
{this.props.features.map( (feature) => {
return (<plugins.Feature
key={feature.id}
crs={projection}
type={feature.type}
geometry={feature.geometry}/>);
})}
Expand All @@ -195,18 +196,19 @@ const MapPlugin = React.createClass({
return this.props.layers.map((layer, index) => {
return (
<plugins.Layer type={layer.type} srs={projection} position={index} key={layer.id || layer.name} options={layer}>
{this.renderLayerContent(layer)}
{this.renderLayerContent(layer, projection)}
</plugins.Layer>
);
}).concat(this.props.features && this.props.features.length && this.getHighlightLayer(projection, this.props.layers.length) || []);
},
renderLayerContent(layer) {
renderLayerContent(layer, projection) {
if (layer.features && layer.type === "vector") {
return layer.features.map( (feature) => {
return (
<plugins.Feature
key={feature.id}
type={feature.type}
crs={projection}
geometry={feature.geometry}
msId={feature.id}
featuresCrs={ layer.featuresCrs || 'EPSG:4326' }
Expand Down

0 comments on commit cf91f48

Please sign in to comment.