improve color saving; improve property handling
This commit is contained in:
@@ -36,7 +36,8 @@ export class AddLayerComponent {
|
|||||||
if (data) {
|
if (data) {
|
||||||
this.formData.layerName = data.name;
|
this.formData.layerName = data.name;
|
||||||
this.formData.layerData = data.data;
|
this.formData.layerData = data.data;
|
||||||
this.formData.color = Utils.rgbToHex(data.color[0],data.color[1],data.color[2]);
|
const colorRgb = data.getDefaultColor();
|
||||||
|
this.formData.color = Utils.rgbToHex(colorRgb[0],colorRgb[1],colorRgb[2]);
|
||||||
this.editMode = true;
|
this.editMode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,8 @@ export class AddLayerComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
const rawLayer = new RawLayer(this.formData.layerName, this.formData.layerData, Utils.hexToRgba(this.formData.color));
|
const rawLayer = new RawLayer(this.formData.layerName, this.formData.layerData);
|
||||||
|
rawLayer.saveDefaultColor(Utils.hexToRgba(this.formData.color));
|
||||||
this.close(rawLayer);
|
this.close(rawLayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ import { LeafletMapComponent } from './leaflet-map/leaflet-map.component';
|
|||||||
import {HttpClient, HttpClientModule} from "@angular/common/http";
|
import {HttpClient, HttpClientModule} from "@angular/common/http";
|
||||||
import {FormsModule} from "@angular/forms";
|
import {FormsModule} from "@angular/forms";
|
||||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||||
import {MatCardModule, MatDialogModule, MatGridListModule, MatInputModule, MatToolbarModule} from "@angular/material";
|
import {
|
||||||
|
MatCardModule,
|
||||||
|
MatDialogModule,
|
||||||
|
MatGridListModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatToolbarModule
|
||||||
|
} from "@angular/material";
|
||||||
import {DragDropModule} from "@angular/cdk/drag-drop";
|
import {DragDropModule} from "@angular/cdk/drag-drop";
|
||||||
import { AddLayerComponent } from './add-layer-component/add-layer.component';
|
import { AddLayerComponent } from './add-layer-component/add-layer.component';
|
||||||
|
|
||||||
@@ -31,6 +38,7 @@ import { AddLayerComponent } from './add-layer-component/add-layer.component';
|
|||||||
DragDropModule,
|
DragDropModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
|
MatTableModule,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
AddLayerComponent
|
AddLayerComponent
|
||||||
|
|||||||
@@ -22,8 +22,14 @@
|
|||||||
<mat-card-title>Layer Properties</mat-card-title>
|
<mat-card-title>Layer Properties</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div>
|
<div *ngFor="let item of currentFeatureInfo | keyvalue" class="entry">
|
||||||
{{ currentFeatureInfo | json}}
|
{{item.key}}
|
||||||
|
<br>
|
||||||
|
{{item.value}}
|
||||||
|
<div class="controls">
|
||||||
|
<i class="material-icons">edit</i>
|
||||||
|
<i class="material-icons">delete</i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|||||||
@@ -38,8 +38,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.layer-control-area {
|
.layer-control-area {
|
||||||
|
|
||||||
|
|
||||||
.layer-list {
|
.layer-list {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border: solid 1px #ccc;
|
border: solid 1px #ccc;
|
||||||
@@ -73,6 +71,25 @@
|
|||||||
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layer-property-area {
|
||||||
|
|
||||||
|
.mat-card-content {
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
display: flex;
|
||||||
|
height: 3rem;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 0 .125rem 0;
|
||||||
|
border: 1px black solid;
|
||||||
|
padding: .5rem;
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cdk-drag-preview {
|
.cdk-drag-preview {
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import LayerGroup from 'ol/layer/Group';
|
|||||||
import {Collection} from "openlayers";
|
import {Collection} from "openlayers";
|
||||||
import {EPSG} from "../enums/EPSG";
|
import {EPSG} from "../enums/EPSG";
|
||||||
import {inAndOut} from 'ol/easing';
|
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';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: add description
|
* TODO: add description
|
||||||
@@ -50,6 +54,35 @@ export class MapComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public currentFeatureInfo: any;
|
public currentFeatureInfo: any;
|
||||||
|
|
||||||
|
public propertyMockData = JSON.parse('{\n' +
|
||||||
|
'\t"FL": "345",\n' +
|
||||||
|
'\t"FLST_LABEL": "93\\/0",\n' +
|
||||||
|
'\t"FLAECHE_HA": 0.19303757998400001,\n' +
|
||||||
|
'\t"FBID": "DEHBEE0433450039",\n' +
|
||||||
|
'\t"FELDBL_NR": "043345-0039",\n' +
|
||||||
|
'\t"BESCHRIFT": "?",\n' +
|
||||||
|
'\t"NUTZER": "?",\n' +
|
||||||
|
'\t"TEILRAUM": "Blockland - Waller Feldmark",\n' +
|
||||||
|
'\t"BAUM17Code": "-",\n' +
|
||||||
|
'\t"B_AUM_2017": "-",\n' +
|
||||||
|
'\t"Parz_Code": "-",\n' +
|
||||||
|
'\t"Nutzung": "Grünland",\n' +
|
||||||
|
'\t"Nat_schutz": "-",\n' +
|
||||||
|
'\t"Gebiet": "Blockland",\n' +
|
||||||
|
'\t"Thema": "Informationen Agrarflächen",\n' +
|
||||||
|
'\t"Flurstck": "Flst. 345: 93\\/0"\n' +
|
||||||
|
'}');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple cache to save styles
|
||||||
|
*/
|
||||||
|
private styleCache: { [key: string]: Style } = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple feature cache
|
||||||
|
*/
|
||||||
|
private featureCache: { [key: string]: Feature } = {};
|
||||||
|
|
||||||
constructor(public dialog: MatDialog) {
|
constructor(public dialog: MatDialog) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,62 +150,64 @@ export class MapComponent implements OnInit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pixel = this.map.getEventPixel(evt.originalEvent);
|
const pixel = this.map.getEventPixel(evt.originalEvent);
|
||||||
this.displayFeatureInfo(pixel);
|
const features = this.map.getFeaturesAtPixel(pixel);
|
||||||
|
if (features && features.length > 0) {
|
||||||
|
this.displayFeatureInfo(features[0]);
|
||||||
|
this.highlightFeature(features[0]);
|
||||||
|
} else {
|
||||||
|
// reapply original style to last highlighted feature
|
||||||
|
if (this.featureCache['lastHighlighted']) {
|
||||||
|
this.featureCache['lastHighlighted'].setStyle(this.styleCache['lastHighlightedStyle']);
|
||||||
|
}
|
||||||
|
// reset cache for feature and style
|
||||||
|
this.featureCache['lastHighlighted'] = null;
|
||||||
|
this.styleCache['lastHighlightedStyle'] = null;
|
||||||
|
this.currentFeatureInfo = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all feature infos for each feature at the given pixel.
|
* Prepared feature properties and shows them
|
||||||
* @param pixel
|
* @param features
|
||||||
*/
|
*/
|
||||||
private displayFeatureInfo(pixel) {
|
private displayFeatureInfo(feature: Feature) {
|
||||||
const features = [];
|
|
||||||
this.map.forEachFeatureAtPixel(pixel, (feature) => {
|
|
||||||
features.push(feature)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (features.length == 0) {
|
|
||||||
this.currentFeatureInfo = 'Too many features. Please zoom in to see feature infos';
|
|
||||||
} else if (features.length == 1) {
|
|
||||||
features.forEach(feature => {
|
|
||||||
const properties = feature.getProperties();
|
const properties = feature.getProperties();
|
||||||
delete properties.geometry;
|
delete properties.geometry;
|
||||||
this.currentFeatureInfo = properties;
|
this.currentFeatureInfo = properties;
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.currentFeatureInfo = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// private colorPolygons(feature: Feature, resolution: any) {
|
/**
|
||||||
// const styles = {
|
* Highlights a Features
|
||||||
// black: new Style({
|
* @param feature
|
||||||
// stroke: new Stroke({
|
*/
|
||||||
// color: '#86665a',
|
private highlightFeature(feature: Feature) {
|
||||||
// width: 1
|
// init case
|
||||||
// }),
|
if (!this.styleCache['defaultHighlight']) {
|
||||||
// fill: new Fill({
|
this.styleCache['defaultHighlight'] = new Style({
|
||||||
// color: 'rgba(121,85,72, 0.4)',
|
stroke: new Stroke({
|
||||||
// })
|
color: 'rgb(245, 64, 41)',
|
||||||
// }),
|
width: 2
|
||||||
// green: new Style({
|
}),
|
||||||
// stroke: new Stroke({
|
fill: new Fill({
|
||||||
// color: '#b8c633',
|
color: 'rgba(245, 64, 41, 0.1)',
|
||||||
// width: 1
|
})
|
||||||
// }),
|
})
|
||||||
// fill: new Fill({
|
}
|
||||||
// color: 'rgba(205,220,57,0.4)',
|
|
||||||
// })
|
// reapply saved feature and style
|
||||||
// })
|
if (this.featureCache['lastHighlighted']) {
|
||||||
// }
|
this.featureCache['lastHighlighted'].setStyle(this.styleCache['lastHighlightedStyle']);
|
||||||
// // console.log(feature.getProperties()['Grünland'],feature.getProperties());
|
}
|
||||||
// if (feature.getProperties()['Nutzung'] === 'Grünland') {
|
// save current feature and style
|
||||||
// return styles.green;
|
this.featureCache['lastHighlighted'] = feature;
|
||||||
// } else {
|
this.styleCache['lastHighlightedStyle'] = feature.getStyle();
|
||||||
// return styles.black;
|
|
||||||
// }
|
// set new feature style
|
||||||
// }
|
feature.setStyle(this.styleCache['defaultHighlight']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a dialog to create a new custom layer
|
* Opens a dialog to create a new custom layer
|
||||||
|
|||||||
+35
-28
@@ -6,7 +6,7 @@ import Style from 'ol/style/Style';
|
|||||||
import Stroke from 'ol/style/Stroke';
|
import Stroke from 'ol/style/Stroke';
|
||||||
import Fill from 'ol/style/Fill';
|
import Fill from 'ol/style/Fill';
|
||||||
import {Config} from "../misc/Config";
|
import {Config} from "../misc/Config";
|
||||||
|
import {Feature} from 'ol/Feature';
|
||||||
/**
|
/**
|
||||||
* Represents a raw (not processed) map layer
|
* Represents a raw (not processed) map layer
|
||||||
*/
|
*/
|
||||||
@@ -19,14 +19,8 @@ export class RawLayer {
|
|||||||
/**
|
/**
|
||||||
* Data of Layer (normally in geojson format)
|
* Data of Layer (normally in geojson format)
|
||||||
*/
|
*/
|
||||||
public data: string,
|
public data: string
|
||||||
/**
|
|
||||||
* Layer stroke color as number array with opacity like -> [255, 255, 255, 0.5]
|
|
||||||
* The fill color is an opaque decreased derivation of this value.
|
|
||||||
*/
|
|
||||||
public color: number[]
|
|
||||||
) {
|
) {
|
||||||
this.saveColorToGeoJSON();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,16 +29,10 @@ export class RawLayer {
|
|||||||
* @param layer
|
* @param layer
|
||||||
*/
|
*/
|
||||||
public static fromVectorLayer(layer: VectorLayer): RawLayer {
|
public static fromVectorLayer(layer: VectorLayer): RawLayer {
|
||||||
const writer = new GeoJSON();
|
|
||||||
const source = layer.getSource();
|
const source = layer.getSource();
|
||||||
|
|
||||||
// get default style values
|
|
||||||
const features = source.getFeatures();
|
const features = source.getFeatures();
|
||||||
const featureProperties = features[0].getProperties();
|
const geoJSONString = RawLayer.featuresToGeoJSON(features);
|
||||||
const rawLayerColor = featureProperties[Config.GEO_JSON_PREFIX]['default-style-stroke'];
|
return new RawLayer(layer.get('name'), geoJSONString);
|
||||||
|
|
||||||
const geoJSONString = writer.writeFeatures(features,{featureProjection: EPSG.openLayersDefault});
|
|
||||||
return new RawLayer(layer.get('name'), geoJSONString, rawLayerColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,10 +41,7 @@ export class RawLayer {
|
|||||||
*/
|
*/
|
||||||
public static toVectorLayer(rawLayer: RawLayer): VectorLayer {
|
public static toVectorLayer(rawLayer: RawLayer): VectorLayer {
|
||||||
const vectorSource = new VectorSource();
|
const vectorSource = new VectorSource();
|
||||||
const geoJSON = new GeoJSON();
|
const features = RawLayer.geoJSONToFeatures(rawLayer.data);
|
||||||
// load geoJSON features from rawLayer
|
|
||||||
const features = geoJSON.readFeatures(rawLayer.data, {featureProjection: EPSG.openLayersDefault});
|
|
||||||
|
|
||||||
// apply style to all features
|
// apply style to all features
|
||||||
features.forEach(feature => {
|
features.forEach(feature => {
|
||||||
// TODO
|
// TODO
|
||||||
@@ -87,20 +72,42 @@ export class RawLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the RawLayer color property to all feature properties from data attribute
|
* Saves a default color property to geoJSON
|
||||||
*/
|
*/
|
||||||
private saveColorToGeoJSON() {
|
public saveDefaultColor(color: number[]) {
|
||||||
const geoJSON = new GeoJSON();
|
const features = RawLayer.geoJSONToFeatures(this.data);
|
||||||
// load geoJSON features from rawLayer
|
|
||||||
const features = geoJSON.readFeatures(this.data, {featureProjection: EPSG.openLayersDefault});
|
|
||||||
features.forEach(feature => {
|
features.forEach(feature => {
|
||||||
// save default color in feature properties
|
// save default color in feature properties
|
||||||
const stylesToSave = {};
|
const stylesToSave = {};
|
||||||
stylesToSave[Config.GEO_JSON_PREFIX] = {};
|
stylesToSave[Config.GEO_JSON_PREFIX] = {};
|
||||||
stylesToSave[Config.GEO_JSON_PREFIX]['default-style-stroke'] = this.color;
|
stylesToSave[Config.GEO_JSON_PREFIX]['default-style-stroke'] = color;
|
||||||
stylesToSave[Config.GEO_JSON_PREFIX]['default-style-fill'] = [...this.color.slice(0, 3), 0.1];
|
stylesToSave[Config.GEO_JSON_PREFIX]['default-style-fill'] = [...color.slice(0, 3), 0.1];
|
||||||
feature.setProperties(stylesToSave);
|
feature.setProperties(stylesToSave);
|
||||||
})
|
})
|
||||||
this.data = geoJSON.writeFeatures(features, {featureProjection: EPSG.openLayersDefault});
|
this.data = RawLayer.featuresToGeoJSON(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the default color property from geoJSON
|
||||||
|
*/
|
||||||
|
public getDefaultColor(): number[]{
|
||||||
|
const features = RawLayer.geoJSONToFeatures(this.data);
|
||||||
|
const featureProperties = features[0].getProperties();
|
||||||
|
return featureProperties[Config.GEO_JSON_PREFIX]['default-style-stroke'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the features from geoJSON
|
||||||
|
*/
|
||||||
|
private static geoJSONToFeatures(geoJSON: string): Feature[] {
|
||||||
|
return new GeoJSON().readFeatures(geoJSON, {featureProjection: EPSG.openLayersDefault});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates geoJSON string from features
|
||||||
|
* @param features
|
||||||
|
*/
|
||||||
|
private static featuresToGeoJSON(features: Feature[]): string {
|
||||||
|
return new GeoJSON().writeFeatures(features, {featureProjection: EPSG.openLayersDefault});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user