FarmMapsLib/projects/common-map/src/fm-map/components/aol/item-vector-source/item-vector-source.componen...

192 lines
7.0 KiB
TypeScript
Raw Normal View History

2023-02-14 15:52:46 +00:00
import { Component, Host, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, forwardRef, Inject, InjectionToken } from '@angular/core';
2020-02-12 19:38:14 +00:00
import { LayerVectorComponent, SourceVectorComponent, MapComponent } from 'ngx-openlayers';
2023-02-14 15:52:46 +00:00
import { ItemService, ItemTypeService, IItem, IItemType } from '@farmmaps/common';
2020-02-12 19:38:14 +00:00
import { Feature } from 'ol';
2023-02-14 15:52:46 +00:00
import { Point, Geometry } from 'ol/geom';
2020-02-12 19:38:14 +00:00
import { MapBrowserEvent } from 'ol';
2021-10-05 14:13:25 +00:00
import { Types } from 'ol/MapBrowserEventType';
2020-02-12 19:38:14 +00:00
import * as style from 'ol/style';
import * as color from 'ol/color';
import * as loadingstrategy from 'ol/loadingstrategy';
import * as condition from 'ol/events/condition';
import * as extent from 'ol/extent';
2023-02-14 15:52:46 +00:00
import { Vector, Cluster, Source } from 'ol/source';
import { Layer } from 'ol/layer';
import { GeoJSON } from 'ol/format';
import { Select } from 'ol/interaction';
import { IStyles } from '../../../models/style.cache';
import { FeatureIconService } from '../../../services/feature-icon.service';
2020-02-12 19:38:14 +00:00
@Component({
selector: 'fm-map-item-source-vector',
template: `<ng-content></ng-content>`,
providers: [
2023-02-14 15:52:46 +00:00
{ provide: SourceVectorComponent, useExisting: forwardRef(() => ItemVectorSourceComponent) }
2020-02-12 19:38:14 +00:00
]
})
export class ItemVectorSourceComponent extends SourceVectorComponent implements OnInit, OnChanges {
2021-10-05 11:46:10 +00:00
instance: Vector<Geometry>;
2020-02-12 19:38:14 +00:00
private _format: GeoJSON;
private _select: Select;
private _hoverSelect: Select;
2023-03-06 13:04:14 +00:00
private _iconScale = 0.05;
2021-10-05 11:46:10 +00:00
@Input() features: Array<Feature<Geometry>>;
@Input() selectedFeature: Feature<Geometry>;
2020-02-12 19:38:14 +00:00
@Input() selectedItem: IItem;
2023-02-14 15:52:46 +00:00
@Input() styles: IStyles;
2021-10-05 11:46:10 +00:00
@Output() onFeatureSelected: EventEmitter<Feature<Geometry>> = new EventEmitter<Feature<Geometry>>();
@Output() onFeatureHover: EventEmitter<Feature<Geometry>> = new EventEmitter<Feature<Geometry>>();
2023-02-14 15:52:46 +00:00
private stylesCache: IStyles = {};
2020-02-12 19:38:14 +00:00
2023-02-14 15:52:46 +00:00
constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, private map: MapComponent, private itemTypeService: ItemTypeService, private featureIconService$: FeatureIconService) {
2020-02-12 19:38:14 +00:00
super(layer);
this._format = new GeoJSON();
2023-02-14 15:52:46 +00:00
}
2020-02-12 19:38:14 +00:00
2021-10-05 11:46:10 +00:00
geometry(feature: Feature<Geometry>) {
2023-03-06 13:04:14 +00:00
const view = this.map.instance.getView();
const resolution = view.getResolution();
let geometry = feature.getGeometry();
const e = geometry.getExtent();
2020-02-12 19:38:14 +00:00
//var size = Math.max((e[2] - e[0]) / resolution, (e[3] - e[1]) / resolution);
if (resolution > 12) {
geometry = new Point(extent.getCenter(e));
}
return geometry;
2023-02-14 15:52:46 +00:00
}
2020-02-12 19:38:14 +00:00
2023-02-14 15:52:46 +00:00
getSelectedStyle(feature: Feature<Geometry>): style.Style {
2023-03-06 13:04:14 +00:00
const key = feature.get('itemType') + "_selected";
2023-02-14 15:52:46 +00:00
let evaluatedStyle: style.Style = undefined;
2023-03-06 13:04:14 +00:00
const styleEntry = this.stylesCache[key];
2023-02-14 15:52:46 +00:00
if (styleEntry) {
if (typeof styleEntry === 'function') {
2020-02-13 15:51:23 +00:00
evaluatedStyle = styleEntry(feature);
} else {
evaluatedStyle = styleEntry;
}
} else {
2021-10-05 12:08:55 +00:00
evaluatedStyle = this.stylesCache["selected"] as style.Style;
2023-02-14 15:52:46 +00:00
}
if (evaluatedStyle) {
evaluatedStyle.setGeometry((feature: Feature<Geometry>) => this.geometry(feature));
}
2021-10-05 11:46:10 +00:00
return evaluatedStyle as style.Style
}
2020-02-12 19:38:14 +00:00
ngOnInit() {
this.strategy = loadingstrategy.bbox;
this.format = new GeoJSON();
this._select = new Select({
2023-02-14 15:52:46 +00:00
style: null,
2020-02-12 19:38:14 +00:00
hitTolerance: 10,
2021-10-05 11:46:10 +00:00
layers: [this.layer.instance as Layer<Source>]
2020-02-12 19:38:14 +00:00
});
this._hoverSelect = new Select({
2023-02-14 15:52:46 +00:00
style: (feature: Feature<Geometry>) => {
return this.getSelectedStyle(feature);
2020-02-12 19:38:14 +00:00
},
hitTolerance: 10,
2021-10-05 14:13:25 +00:00
condition: (e: MapBrowserEvent<UIEvent>) => {
2020-02-12 19:38:14 +00:00
return e.type == 'pointermove';
},
2021-10-05 11:46:10 +00:00
layers: [this.layer.instance as Layer<Source>]
2020-02-12 19:38:14 +00:00
});
this.map.instance.addInteraction(this._select);
2023-02-14 15:52:46 +00:00
this.map.instance.addInteraction(this._hoverSelect);
2020-02-12 19:38:14 +00:00
this._select.on('select', (e) => {
if (e.selected.length > 0 && e.selected[0]) {
2020-10-29 18:14:06 +00:00
this.onFeatureSelected.emit(e.selected[0]);
2020-02-12 19:38:14 +00:00
} else {
2020-10-29 18:14:06 +00:00
this.onFeatureSelected.emit(null);
2020-02-12 19:38:14 +00:00
}
});
2020-04-16 11:19:06 +00:00
this._hoverSelect.on('select', (e) => {
if (e.selected.length > 0 && e.selected[0]) {
this.onFeatureHover.emit(e.selected[0]);
} else {
this.onFeatureHover.emit(null);
}
});
2020-02-12 19:38:14 +00:00
this.instance = new Vector(this);
this.host.instance.setSource(this.instance);
2023-02-14 15:52:46 +00:00
this.host.instance.setStyle((feature) => {
2023-03-06 13:04:14 +00:00
const itemType = feature.get('itemType');
let key = itemType + (this.selectedItem ? "_I" : "");
2020-02-12 20:33:28 +00:00
if (!this.stylesCache[key]) {
2021-08-12 19:02:55 +00:00
if (this.itemTypeService.itemTypes[itemType]) {
2023-03-06 13:04:14 +00:00
const itemTypeEntry = this.itemTypeService.itemTypes[itemType];
const fillColor = color.asArray(itemTypeEntry.iconColor);
2021-01-26 08:12:37 +00:00
fillColor[3] = 0;
2020-02-12 20:33:28 +00:00
this.stylesCache[key] = new style.Style({
2023-02-14 15:52:46 +00:00
image: itemTypeEntry.icon ? new style.Icon({
anchor: [0.5, 1],
scale: 0.05,
src: this.featureIconService$.getIconImageDataUrl(itemTypeEntry.icon)
}) : null,
stroke: new style.Stroke({
color: 'red',
width: 1
}),
fill: new style.Fill({
color: fillColor
}),
geometry: (feature: Feature<Geometry>) => this.geometry(feature)
});
2020-02-12 19:38:14 +00:00
} else {
key = 'file';
}
2023-02-14 15:52:46 +00:00
}
let evaluatedStyle = null;
2023-03-06 13:04:14 +00:00
const styleEntry = this.stylesCache[key];
2023-02-14 15:52:46 +00:00
if (typeof styleEntry === 'function') {
2020-02-13 15:14:18 +00:00
evaluatedStyle = styleEntry(feature);
} else {
evaluatedStyle = styleEntry;
}
2023-02-14 16:22:26 +00:00
if (evaluatedStyle && evaluatedStyle.geometry_ == null && !Array.isArray(evaluatedStyle)) {
2020-02-13 15:14:18 +00:00
evaluatedStyle.setGeometry((feature) => this.geometry(feature));
2023-02-14 15:52:46 +00:00
}
2020-02-13 15:14:18 +00:00
return evaluatedStyle;
2020-02-12 19:38:14 +00:00
});
}
ngOnChanges(changes: SimpleChanges) {
if (changes["features"] && this.instance) {
this.instance.clear(true);
this._select.getFeatures().clear();
this.instance.addFeatures(changes["features"].currentValue);
}
if (changes["selectedFeature"] && this.instance) {
2023-03-06 13:04:14 +00:00
const features = this._hoverSelect.getFeatures();
const feature = changes["selectedFeature"].currentValue
2020-02-12 19:38:14 +00:00
//this.instance.clear(false);
//this.instance.addFeatures(features.getArray());
features.clear();
if (feature) {
//this.instance.removeFeature(feature);
features.push(feature)
2023-02-14 15:52:46 +00:00
}
2020-02-12 19:38:14 +00:00
}
if (changes["selectedItem"] && this.instance) {
2023-03-06 13:04:14 +00:00
const item = changes["selectedItem"].currentValue
2020-02-12 19:38:14 +00:00
if (item) {
2023-02-14 15:52:46 +00:00
this.map.instance.removeInteraction(this._hoverSelect);
2020-02-12 19:38:14 +00:00
} else {
2023-02-14 15:52:46 +00:00
this.map.instance.addInteraction(this._hoverSelect);
2020-02-12 19:38:14 +00:00
}
}
2023-02-14 15:52:46 +00:00
if (changes["styles"]) {
2023-03-06 13:04:14 +00:00
const styles = changes["styles"].currentValue;
2020-02-12 20:33:28 +00:00
for (const key in styles) {
if (styles.hasOwnProperty(key)) {
2023-02-14 15:52:46 +00:00
this.stylesCache[key] = styles[key];
2020-02-12 20:33:28 +00:00
}
}
}
2020-02-12 19:38:14 +00:00
}
}