Refactor style cache
This commit is contained in:
@@ -1,207 +1,146 @@
|
||||
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';
|
||||
|
||||
@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;
|
||||
@Output() onFeaturesSelected: EventEmitter<Feature> = new EventEmitter<Feature>();
|
||||
private styleCache = {
|
||||
'file': new style.Style({
|
||||
image: new style.Icon({
|
||||
anchor: [0.5, 1],
|
||||
scale: 0.05,
|
||||
src: this.getIconImageDataUrl("fa fa-file-o")
|
||||
}),
|
||||
stroke: new style.Stroke({
|
||||
color: 'red',
|
||||
width: 1
|
||||
}),
|
||||
fill: new style.Fill({
|
||||
color: 'rgba(0, 0, 255, 0.1)'
|
||||
}),
|
||||
geometry: (feature) => this.geometry(feature)
|
||||
}),
|
||||
'selected': new style.Style({
|
||||
image: new style.Icon({
|
||||
anchor: [0.5, 1],
|
||||
scale: 0.08,
|
||||
src: this.getIconImageDataUrl(null)
|
||||
}),
|
||||
stroke: new style.Stroke({
|
||||
color: 'red',
|
||||
width: 3
|
||||
}),
|
||||
fill: new style.Fill({
|
||||
color: 'rgba(0, 0, 255, 0.1)'
|
||||
}),
|
||||
geometry: (feature) => this.geometry(feature)
|
||||
})
|
||||
};
|
||||
|
||||
constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, @Host() private map: MapComponent, private itemTypeService: ItemTypeService) {
|
||||
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;
|
||||
}
|
||||
|
||||
getIconImageDataUrl(iconClass:string, backgroundColor: string = "#c80a6e",color:string = "#ffffff"): string {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 365;
|
||||
canvas.height = 560;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.lineWidth = 6;
|
||||
ctx.fillStyle = backgroundColor;
|
||||
ctx.strokeStyle = "#000000";
|
||||
var path = new Path2D("m182.9 551.7c0 0.1 0.2 0.3 0.2 0.3s175.2-269 175.2-357.4c0-130.1-88.8-186.7-175.4-186.9-86.6 0.2-175.4 56.8-175.4 186.9 0 88.4 175.3 357.4 175.3 357.4z");
|
||||
ctx.fill(path)
|
||||
|
||||
var iconCharacter = "";
|
||||
if (iconClass != null) {
|
||||
var element = document.createElement("i");
|
||||
element.style.display = "none";
|
||||
element.className = iconClass;
|
||||
document.body.appendChild(element);
|
||||
iconCharacter = getComputedStyle(element, "::before").content.replace(/"/g, '');
|
||||
let iconFont = "200px " +getComputedStyle(element, "::before").fontFamily
|
||||
document.body.removeChild(element);
|
||||
ctx.strokeStyle = color;
|
||||
ctx.fillStyle = color;
|
||||
ctx.lineWidth = 15;
|
||||
ctx.font = iconFont;
|
||||
var ts = ctx.measureText(iconCharacter);
|
||||
ctx.fillText(iconCharacter, 182.9 - (ts.width / 2), 250);
|
||||
ctx.strokeText(iconCharacter, 182.9 - (ts.width / 2), 250);
|
||||
}
|
||||
|
||||
return canvas.toDataURL();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.strategy = loadingstrategy.bbox;
|
||||
this.format = new GeoJSON();
|
||||
this._select = new Select({
|
||||
style: (feature) => {
|
||||
return this.styleCache['selected'];
|
||||
},
|
||||
hitTolerance: 10,
|
||||
layers: [this.layer.instance as Layer]
|
||||
});
|
||||
this._hoverSelect = new Select({
|
||||
style: (feature) => {
|
||||
return this.styleCache['selected'];
|
||||
},
|
||||
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.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.styleCache[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.styleCache[key] = new style.Style({
|
||||
image: itemType.icon ? new style.Icon({
|
||||
anchor: [0.5, 1],
|
||||
scale: 0.05,
|
||||
src: this.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';
|
||||
}
|
||||
}
|
||||
var styleEntry = this.styleCache[key];
|
||||
return styleEntry;
|
||||
});
|
||||
}
|
||||
|
||||
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._select.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {IStyleCache} 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;
|
||||
@Output() onFeaturesSelected: EventEmitter<Feature> = new EventEmitter<Feature>();
|
||||
private styleCache:IStyleCache = {};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.strategy = loadingstrategy.bbox;
|
||||
this.format = new GeoJSON();
|
||||
this._select = new Select({
|
||||
style: (feature) => {
|
||||
return this.styleCache['selected'];
|
||||
},
|
||||
hitTolerance: 10,
|
||||
layers: [this.layer.instance as Layer]
|
||||
});
|
||||
this._hoverSelect = new Select({
|
||||
style: (feature) => {
|
||||
return this.styleCache['selected'];
|
||||
},
|
||||
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.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.styleCache[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.styleCache[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
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
key = 'file';
|
||||
}
|
||||
}
|
||||
var styleEntry = this.styleCache[key];
|
||||
styleEntry.geometry = (feature) => this.geometry(feature);
|
||||
return styleEntry;
|
||||
});
|
||||
}
|
||||
|
||||
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._select.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user