= new EventEmitter();
/**
* The color style of the color preview
*/
- previewStyle : any;
+ previewStyle: any;
/**
* A simple flag that is true, if the default color is active
*/
- isDefaultColor : boolean;
+ isDefaultColor: boolean = true;
- ngOnInit(){
+ ngOnInit() {
this.definePreviewStyle();
}
@@ -71,18 +82,16 @@ export class CustomColorEntryComponent implements OnInit{
* Returns the style for the preview. If a color was defined, this color is used. If not, the default color is used
* instead.
*/
- definePreviewStyle(): any {
+ definePreviewStyle() {
let styles = {
'border-color': this.defaultStrokeColorAsRgba,
'background-color': this.defaultFillColorAsRgba
};
- this.isDefaultColor = true;
- if (this.selectedColor) {
+ if (!this.isDefaultColor) {
styles = {
'border-color': this.strokeColorAsRgba,
'background-color': this.fillColorAsRgba
};
- this.isDefaultColor = false;
}
this.previewStyle = styles;
}
@@ -91,20 +100,30 @@ export class CustomColorEntryComponent implements OnInit{
* Saves the given hex value to colors object as not default color
* @param value
*/
- applyColor(value: any) {
+ applyColor(value: string) {
this.colors[CustomProperties.COLOR_STROKE] = Utils.hexToRgba(value);
this.colors[CustomProperties.COLOR_FILL] = Utils.hexToRgba(value, Config.DEFAULT_FILL_OPACITY_TO_STROKE);
this.definePreviewStyle();
}
/**
- * TODO add description
+ * Resets the custom color
*/
- resetColor(){
+ resetColor() {
this.colors[CustomProperties.COLOR_STROKE] = null;
this.colors[CustomProperties.COLOR_FILL] = null;
+ this.isDefaultColor = true;
this._selectedColor = null;
this.definePreviewStyle();
+ this.colorChangeEmitter.emit(this.colors);
}
+ /**
+ * Eventhandler that is fired when a color is picked
+ * @param event
+ */
+ onColorPicked(color: string) {
+ this.selectedColor = color;
+ this.isDefaultColor = false;
+ }
}
diff --git a/src/app/feature-management/feature-manager/feature-manager.component.html b/src/app/feature-management/feature-manager/feature-manager.component.html
index 5571530..1fb95d1 100644
--- a/src/app/feature-management/feature-manager/feature-manager.component.html
+++ b/src/app/feature-management/feature-manager/feature-manager.component.html
@@ -23,8 +23,8 @@
-
+
diff --git a/src/app/feature-management/feature-manager/feature-manager.component.ts b/src/app/feature-management/feature-manager/feature-manager.component.ts
index 91fad8e..9568bc6 100644
--- a/src/app/feature-management/feature-manager/feature-manager.component.ts
+++ b/src/app/feature-management/feature-manager/feature-manager.component.ts
@@ -1,8 +1,8 @@
-import {Component, Input} from "@angular/core";
-// import {Feature} from 'ol/Feature';
-import {Config} from "../../misc/Config";
-import {CustomProperties} from "../../enums/CustomProperties";
+import {Component, Input, Output, EventEmitter} from '@angular/core';
+import {Config} from '../../misc/Config';
+import {CustomProperties} from '../../enums/CustomProperties';
import {Feature} from 'ol/Feature';
+import {RawLayer} from 'src/app/models/RawLayer';
/**
* This component manages all properties of the current feature. It does not matter if it is a simple geo json
@@ -29,6 +29,11 @@ export class FeatureManagerComponent {
return this._curFeature;
}
+ /**
+ * An event emitter that is fired if a feature is changed,
+ */
+ @Output('featureChange') featureChangeEmitter: EventEmitter = new EventEmitter();
+
/**
* Returns the properties of curFeature
*/
@@ -37,7 +42,6 @@ export class FeatureManagerComponent {
delete properties.geometry;
delete properties[Config.GEO_JSON_PREFIX];
return properties;
-
}
/**
@@ -46,13 +50,12 @@ export class FeatureManagerComponent {
get curCustomProperties(): any {
const properties = this.curFeature.getProperties();
return properties[Config.GEO_JSON_PREFIX];
-
}
/**
* Returns the default color properties of the current feature
*/
- get curCustomDefaultColor(): any {
+ get curFeatureColors(): any {
const colors = {};
colors[CustomProperties.DEFAULT_COLOR_STROKE] = this.curCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE];
colors[CustomProperties.DEFAULT_COLOR_FILL] = this.curCustomProperties[CustomProperties.DEFAULT_COLOR_FILL];
@@ -61,8 +64,14 @@ export class FeatureManagerComponent {
return colors;
}
- defaultColorChanged(colors: any) {
- console.log('Default colors changed!', colors);
+ /**
+ * Event handler if the color set of a feature was changed
+ * @param colors
+ */
+ onFeatureColorChanged(colors: any) {
+ RawLayer.saveCustomProperties(this.curFeature, colors);
+ this.curFeature.setStyle(RawLayer.determineColorStyle(colors));
+ this.featureChangeEmitter.emit(this.curFeature);
}
}
diff --git a/src/app/map/map.component.ts b/src/app/map/map.component.ts
index 62dd618..9757dd8 100644
--- a/src/app/map/map.component.ts
+++ b/src/app/map/map.component.ts
@@ -5,19 +5,19 @@ import TileLayer from 'ol/layer/Tile';
import {fromLonLat, transform} from 'ol/proj';
import VectorLayer from 'ol/layer/Vector';
import {OSM} from 'ol/source';
-import {CdkDragDrop} from "@angular/cdk/drag-drop";
-import {MatDialog} from "@angular/material";
-import {AddLayerComponent} from "../add-layer-component/add-layer.component";
-import {RawLayer} from "../models/RawLayer";
+import {CdkDragDrop} from '@angular/cdk/drag-drop';
+import {MatDialog} from '@angular/material';
+import {AddLayerComponent} from '../add-layer-component/add-layer.component';
+import {RawLayer} from '../models/RawLayer';
import LayerGroup from 'ol/layer/Group';
-import {Collection} from "openlayers";
-import {EPSG} from "../enums/EPSG";
+import {Collection} from 'openlayers';
+import {EPSG} from '../enums/EPSG';
import {inAndOut} from 'ol/easing';
import {Feature} from 'ol/Feature';
import Style from 'ol/style/Style';
import Stroke from 'ol/style/Stroke';
import Fill from 'ol/style/Fill';
-import {FeatureManagerComponent} from "../feature-management/feature-manager/feature-manager.component";
+import {FeatureManagerComponent} from '../feature-management/feature-manager/feature-manager.component';
/**
* TODO: add description
@@ -60,6 +60,11 @@ export class MapComponent implements OnInit {
*/
selectedFeature: null,
+ // /**
+ // * The layer of the selected feature
+ // */
+ // selectedLayer: null,
+
/**
* The feature that was highlighted at least
*/
@@ -76,7 +81,7 @@ export class MapComponent implements OnInit {
defaultSelectedStyle: null,
/**
- * Default style for a highlighted feauture
+ * Default style for a highlighted feature
*/
defaultHighlightStyle: null
};
@@ -127,18 +132,18 @@ export class MapComponent implements OnInit {
})
});
- this.addMapEventlistener();
-
+ this.addMapEventListener();
+ this.addFeatureManagerEventListener();
// without this line the map is only visible after resizing window
requestAnimationFrame(() => {
this.map.updateSize();
- })
+ });
}
/**
* Adds all map event listener
*/
- private addMapEventlistener() {
+ private addMapEventListener() {
// get current cursor coordinates to transform and display them
this.map.on('pointermove', (evt) => {
const tmpCoords = transform(evt.coordinate, EPSG.openLayersDefault, EPSG.wgs84);
@@ -152,6 +157,7 @@ export class MapComponent implements OnInit {
}
const pixel = this.map.getEventPixel(evt.originalEvent);
const features = this.map.getFeaturesAtPixel(pixel);
+
if (features && features.length > 0) {
this.map.getTargetElement().style.cursor = 'pointer';
this.featureManager.curFeature = features[0];
@@ -172,23 +178,45 @@ export class MapComponent implements OnInit {
// handle feature selection
this.map.on('click', (evt) => {
const pixel = this.map.getEventPixel(evt.originalEvent);
- const features = this.map.getFeaturesAtPixel(pixel);
+ // const features = this.map.getFeaturesAtPixel(pixel);
+ let selectedFeature;
+ // let selectedLayer;
+ // get the feature and the according layer
+ this.map.forEachFeatureAtPixel(pixel, (feature, layer) => {
+ selectedFeature = feature;
+ // selectedLayer = layer;
+ return true;
+ });
if (this.cache.selectedFeature) {
// use lastHighlightedStyle because the original style is saved there
- this.cache.selectedFeature.setStyle(this.cache.lastHighlightedStyle);
- // this.styleCache['lastHighlightedStyle'] = null;
+ if (this.cache.lastHighlightedStyle) {
+ this.cache.selectedFeature.setStyle(this.cache.lastHighlightedStyle);
+ }
this.cache.selectedFeature = null;
- } else if (features && features.length > 0) {
+ // this.cache.selectedLayer = null;
+ } else if (selectedFeature) {
this.map.getTargetElement().style.cursor = '';
- this.featureManager.curFeature = features[0];
- this.cache.selectedFeature = features[0];
+ this.cache.selectedFeature = selectedFeature;
+ // this.cache.selectedLayer = selectedLayer;
+ this.featureManager.curFeature = this.cache.selectedFeature;
this.cache.lastHighlightedFeature = null;
- features[0].setStyle(this.cache.defaultSelectedStyle);
+ this.cache.selectedFeature.setStyle(this.cache.defaultSelectedStyle);
}
});
}
+ /**
+ * Adds all feature manager event listener
+ */
+ private addFeatureManagerEventListener() {
+ this.featureManager.featureChangeEmitter.subscribe(() => {
+ // - reset selection values
+ // this.cache.selectedFeature = null;
+ this.cache.lastHighlightedStyle = null;
+ });
+ }
+
/**
* Highlights a Features
* @param feature
@@ -282,7 +310,7 @@ export class MapComponent implements OnInit {
size: this.map.getSize(),
duration: 888,
easing: inAndOut
- }
+ };
this.map.getView().fit(customLayer.getSource().getExtent(), options);
}
@@ -298,7 +326,7 @@ export class MapComponent implements OnInit {
fill: new Fill({
color: 'rgba(245, 64, 41, 0.3)',
})
- })
+ });
this.cache.defaultHighlightStyle = new Style({
stroke: new Stroke({
@@ -308,7 +336,7 @@ export class MapComponent implements OnInit {
fill: new Fill({
color: 'rgba(245, 64, 41, 0.1)',
})
- })
+ });
}
/**
@@ -316,22 +344,22 @@ export class MapComponent implements OnInit {
*/
private addMockData() {
const data = {
- "type": "FeatureCollection",
- "name": "background",
- "crs": {
- "type": "name",
- "properties": {
- "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
+ 'type': 'FeatureCollection',
+ 'name': 'background',
+ 'crs': {
+ 'type': 'name',
+ 'properties': {
+ 'name': 'urn:ogc:def:crs:OGC:1.3:CRS84'
}
},
- "features": [{
- "type": "Feature",
- "properties": {
- "name": "Layer 1"
+ 'features': [{
+ 'type': 'Feature',
+ 'properties': {
+ 'name': 'Layer 1'
},
- "geometry": {
- "type": "MultiPolygon",
- "coordinates": [
+ 'geometry': {
+ 'type': 'MultiPolygon',
+ 'coordinates': [
[
[
[8.801864395832126, 53.14770721254275],
@@ -344,13 +372,13 @@ export class MapComponent implements OnInit {
}
},
{
- "type": "Feature",
- "properties": {
- "name": "Layer 2"
+ 'type': 'Feature',
+ 'properties': {
+ 'name': 'Layer 2'
},
- "geometry": {
- "type": "MultiPolygon",
- "coordinates": [
+ 'geometry': {
+ 'type': 'MultiPolygon',
+ 'coordinates': [
[
[
[8.807787400997881, 53.1477644198588],
@@ -363,13 +391,13 @@ export class MapComponent implements OnInit {
}
},
{
- "type": "Feature",
- "properties": {
- "name": "Layer 3"
+ 'type': 'Feature',
+ 'properties': {
+ 'name': 'Layer 3'
},
- "geometry": {
- "type": "MultiPolygon",
- "coordinates": [
+ 'geometry': {
+ 'type': 'MultiPolygon',
+ 'coordinates': [
[
[
[8.80207966021419, 53.14392919393571],
@@ -382,13 +410,13 @@ export class MapComponent implements OnInit {
}
},
{
- "type": "Feature",
- "properties": {
- "name": "Layer 4"
+ 'type': 'Feature',
+ 'properties': {
+ 'name': 'Layer 4'
},
- "geometry": {
- "type": "MultiPolygon",
- "coordinates": [
+ 'geometry': {
+ 'type': 'MultiPolygon',
+ 'coordinates': [
[
[
[8.808654874418039, 53.143631496039035],
@@ -403,7 +431,7 @@ export class MapComponent implements OnInit {
]
};
const rawLayer = new RawLayer('Mock Data Layer', JSON.stringify(data));
- rawLayer.saveDefaultColor([125, 125, 125])
+ rawLayer.saveDefaultColor([125, 125, 125]);
const customLayer = RawLayer.toVectorLayer(rawLayer);
this.centerLayerOnMap(customLayer);
this.customLayerCollection.push(customLayer);
diff --git a/src/app/models/RawLayer.ts b/src/app/models/RawLayer.ts
index b36dfbd..43f60cf 100644
--- a/src/app/models/RawLayer.ts
+++ b/src/app/models/RawLayer.ts
@@ -1,13 +1,13 @@
import VectorLayer from 'ol/layer/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import {Vector as VectorSource} from 'ol/source';
-import {EPSG} from "../enums/EPSG";
+import {EPSG} from '../enums/EPSG';
import Style from 'ol/style/Style';
import Stroke from 'ol/style/Stroke';
import Fill from 'ol/style/Fill';
-import {Config} from "../misc/Config";
+import {Config} from '../misc/Config';
import {Feature} from 'ol/Feature';
-import {CustomProperties} from "../enums/CustomProperties";
+import {CustomProperties} from '../enums/CustomProperties';
/**
* Represents a raw (not processed) map layer
@@ -38,7 +38,7 @@ export class RawLayer {
}
/**
- * Creates a VectorLayer instance from a RawLayer and applies the layer color to all features
+ * Creates a VectorLayer instance from a RawLayer and applies the layer or custom color to all features
* @param rawLayer
*/
public static toVectorLayer(rawLayer: RawLayer): VectorLayer {
@@ -46,21 +46,9 @@ export class RawLayer {
const features = RawLayer.geoJSONToFeatures(rawLayer.data);
// apply style to all features
features.forEach(feature => {
- // TODO
- // determine if this feature has a own color! If so, do not apply default color and use own color.
const featureCustomProperties = RawLayer.getCustomProperties(feature);
- if (featureCustomProperties && featureCustomProperties['default-style-stroke']) {
- feature.setStyle(new Style({
- stroke: new Stroke({
- color: featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE],
- width: 1
- }),
- fill: new Fill({
- color: featureCustomProperties[CustomProperties.DEFAULT_COLOR_FILL]
- })
- }));
- }
- })
+ feature.setStyle(this.determineColorStyle(featureCustomProperties));
+ });
// add features to source
vectorSource.addFeatures(features);
@@ -72,33 +60,6 @@ export class RawLayer {
});
}
- /**
- * Saves a default color property to geoJSON
- */
- public saveDefaultColor(color: number[]) {
- const features = RawLayer.geoJSONToFeatures(this.data);
- features.forEach(feature => {
- // save default color in feature properties
- const properties = {};
- properties[CustomProperties.DEFAULT_COLOR_STROKE] = color;
- properties[CustomProperties.DEFAULT_COLOR_FILL] = [...color.slice(0, 3), Config.DEFAULT_FILL_OPACITY_TO_STROKE];
- RawLayer.saveCustomProperties(feature, properties);
- })
- this.data = RawLayer.featuresToGeoJSON(features);
- }
-
- /**
- * Reads the default color property from geoJSON
- */
- public getDefaultColor(): number[] {
- const features = RawLayer.geoJSONToFeatures(this.data);
- const featureCustomProperties = RawLayer.getCustomProperties(features[0]);
- if (featureCustomProperties && featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE]) {
- return featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE];
- }
- return null;
- }
-
/**
* Creates the features from geoJSON
*/
@@ -123,7 +84,7 @@ export class RawLayer {
const newProperties = {};
// consider custom properties that were saved before
const savedProperties = RawLayer.getCustomProperties(feature);
- newProperties[Config.GEO_JSON_PREFIX] = {...savedProperties,...properties};
+ newProperties[Config.GEO_JSON_PREFIX] = {...savedProperties, ...properties};
feature.setProperties(newProperties);
}
@@ -135,4 +96,63 @@ export class RawLayer {
const featureProperties = feature.getProperties();
return featureProperties[Config.GEO_JSON_PREFIX];
}
+
+
+ /**
+ * Determines which color style should be applied. If no custom color property is provided, the default
+ * color is used.
+ * @param featureCustomProperties
+ */
+ public static determineColorStyle(featureCustomProperties: { [key: string]: any }): Style {
+ if (featureCustomProperties && featureCustomProperties[CustomProperties.COLOR_STROKE]) {
+ return new Style({
+ stroke: new Stroke({
+ color: featureCustomProperties[CustomProperties.COLOR_STROKE],
+ width: 1
+ }),
+ fill: new Fill({
+ color: featureCustomProperties[CustomProperties.COLOR_FILL]
+ })
+ });
+ } else if (featureCustomProperties && featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE]) {
+ return new Style({
+ stroke: new Stroke({
+ color: featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE],
+ width: 1
+ }),
+ fill: new Fill({
+ color: featureCustomProperties[CustomProperties.DEFAULT_COLOR_FILL]
+ })
+ });
+ } else {
+ throw new Error('no color properties are defined');
+ }
+ }
+
+ /**
+ * Saves a default color property to geoJSON
+ */
+ public saveDefaultColor(color: number[]) {
+ const features = RawLayer.geoJSONToFeatures(this.data);
+ features.forEach(feature => {
+ // save default color in feature properties
+ const properties = {};
+ properties[CustomProperties.DEFAULT_COLOR_STROKE] = color;
+ properties[CustomProperties.DEFAULT_COLOR_FILL] = [...color.slice(0, 3), Config.DEFAULT_FILL_OPACITY_TO_STROKE];
+ RawLayer.saveCustomProperties(feature, properties);
+ });
+ this.data = RawLayer.featuresToGeoJSON(features);
+ }
+
+ /**
+ * Reads the default color property from geoJSON
+ */
+ public getDefaultColor(): number[] {
+ const features = RawLayer.geoJSONToFeatures(this.data);
+ const featureCustomProperties = RawLayer.getCustomProperties(features[0]);
+ if (featureCustomProperties && featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE]) {
+ return featureCustomProperties[CustomProperties.DEFAULT_COLOR_STROKE];
+ }
+ return null;
+ }
}