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,Geometry } from 'ol/geom'; import { MapBrowserEvent } from 'ol'; import { Types } from 'ol/MapBrowserEventType'; 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,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'; @Component({ selector: 'fm-map-item-source-vector', template: ``, 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>; @Input() selectedFeature: Feature; @Input() selectedItem: IItem; @Input() styles:IStyles; @Output() onFeatureSelected: EventEmitter> = new EventEmitter>(); @Output() onFeatureHover: EventEmitter> = new EventEmitter>(); private stylesCache:IStyles = {}; constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, 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: style.Style =undefined; var styleEntry = this.stylesCache[key]; if(styleEntry) { if(typeof styleEntry === 'function') { evaluatedStyle = styleEntry(feature); } else { evaluatedStyle = styleEntry; } } else { evaluatedStyle = this.stylesCache["selected"] as style.Style; } if(evaluatedStyle ) { evaluatedStyle .setGeometry((feature:Feature) => this.geometry(feature)); } return evaluatedStyle as style.Style } 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: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.onFeatureSelected.emit(e.selected[0]); } else { this.onFeatureSelected.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 itemType = feature.get('itemType'); var key = itemType + (this.selectedItem?"_I":""); if (!this.stylesCache[key]) { if (this.itemTypeService.itemTypes[itemType]) { let itemTypeEntry = this.itemTypeService.itemTypes[itemType]; let fillColor = color.asArray(itemTypeEntry.iconColor); fillColor[3] = 0; this.stylesCache[key] = new style.Style({ 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) => 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]; } } } } }