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

190 lines
6.7 KiB
TypeScript

import { Component, Host, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, forwardRef, Inject, InjectionToken } from '@angular/core';
import { LayerVectorComponent, SourceVectorComponent, MapComponent } from 'ngx-openlayers';
import { ItemService,ItemTypeService,IItem, IItemType } from '@farmmaps/common';
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import { MapBrowserEvent } from 'ol';
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';
import {Vector,Cluster} 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';
@Component({
selector: 'fm-map-item-source-vector',
template: `<ng-content></ng-content>`,
providers: [
{ provide: SourceVectorComponent , useExisting: forwardRef(() => ItemVectorSourceComponent) }
]
})
export class ItemVectorSourceComponent extends SourceVectorComponent implements OnInit, OnChanges {
instance: Vector;
private _format: GeoJSON;
private _select: Select;
private _hoverSelect: Select;
private _iconScale: number = 0.05;
@Input() features: Array<Feature>;
@Input() selectedFeature: Feature;
@Input() selectedItem: IItem;
@Input() styles:IStyles;
@Output() onFeaturesSelected: EventEmitter<Feature> = new EventEmitter<Feature>();
@Output() onFeatureHover: EventEmitter<Feature> = new EventEmitter<Feature>();
private stylesCache:IStyles = {};
constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, @Host() private map: MapComponent, private itemTypeService: ItemTypeService,private featureIconService$:FeatureIconService) {
super(layer);
this._format = new GeoJSON();
}
geometry(feature: Feature) {
let view = this.map.instance.getView();
let resolution = view.getResolution();
var geometry = feature.getGeometry();
let e = geometry.getExtent();
//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;
}
getSelectedStyle(feature:Feature):style.Style {
let key = feature.get('itemType')+"_selected";
let evaluatedStyle =null;
var styleEntry = this.stylesCache[key];
if(styleEntry) {
if(typeof styleEntry === 'function') {
evaluatedStyle = styleEntry(feature);
} else {
evaluatedStyle = styleEntry;
}
} else {
evaluatedStyle = this.stylesCache["selected"];
}
if(evaluatedStyle ) {
evaluatedStyle.setGeometry((feature) => this.geometry(feature));
}
return evaluatedStyle
}
ngOnInit() {
this.strategy = loadingstrategy.bbox;
this.format = new GeoJSON();
this._select = new Select({
style:null,
hitTolerance: 10,
layers: [this.layer.instance as Layer]
});
this._hoverSelect = new Select({
style: (feature) => {
return this.getSelectedStyle(feature);
},
hitTolerance: 10,
condition: (e: MapBrowserEvent) => {
return e.type == 'pointermove';
},
layers: [this.layer.instance as Layer]
});
this.map.instance.addInteraction(this._select);
this.map.instance.addInteraction(this._hoverSelect);
this._select.on('select', (e) => {
if (e.selected.length > 0 && e.selected[0]) {
this.onFeaturesSelected.emit(e.selected[0]);
} else {
this.onFeaturesSelected.emit(null);
}
});
this._hoverSelect.on('select', (e) => {
if (e.selected.length > 0 && e.selected[0]) {
this.onFeatureHover.emit(e.selected[0]);
} else {
this.onFeatureHover.emit(null);
}
});
this.instance = new Vector(this);
this.host.instance.setSource(this.instance);
this.host.instance.setStyle((feature) => {
var key = feature.get('itemType') + (this.selectedItem?"_I":"");
if (!this.stylesCache[key]) {
if (this.itemTypeService.itemTypes[key]) {
let itemType = this.itemTypeService.itemTypes[key];
let fillColor = color.asArray(itemType.iconColor);
fillColor[3] = this.selectedItem?0:0.5;
this.stylesCache[key] = new style.Style({
image: itemType.icon ? new style.Icon({
anchor: [0.5, 1],
scale: 0.05,
src: this.featureIconService$.getIconImageDataUrl(itemType.icon)
}):null,
stroke: new style.Stroke({
color: 'red',
width: 1
}),
fill: new style.Fill({
color: fillColor
}),
geometry:(feature) => this.geometry(feature)
});
} else {
key = 'file';
}
}
let evaluatedStyle =null;
var styleEntry = this.stylesCache[key];
if(typeof styleEntry === 'function') {
evaluatedStyle = styleEntry(feature);
} else {
evaluatedStyle = styleEntry;
}
if(evaluatedStyle && evaluatedStyle.geometry_ == null) {
evaluatedStyle.setGeometry((feature) => this.geometry(feature));
}
return evaluatedStyle;
});
}
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) {
var features = this._hoverSelect.getFeatures();
var feature = changes["selectedFeature"].currentValue
//this.instance.clear(false);
//this.instance.addFeatures(features.getArray());
features.clear();
if (feature) {
//this.instance.removeFeature(feature);
features.push(feature)
}
}
if (changes["selectedItem"] && this.instance) {
var item = changes["selectedItem"].currentValue
if (item) {
this.map.instance.removeInteraction(this._hoverSelect);
} else {
this.map.instance.addInteraction(this._hoverSelect);
}
}
if (changes["styles"] && this.instance) {
let styles = changes["styles"].currentValue;
for (const key in styles) {
if (styles.hasOwnProperty(key)) {
this.stylesCache[key]=styles[key];
}
}
}
}
}