From 86cb97adf6b1692277695fab7089f4a559346cc2 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 2 Oct 2020 14:04:31 -0400 Subject: [PATCH] [Maps] Simplify IDynamicStyle-api (#79217) --- .../properties/dynamic_style_property.tsx | 54 ++++++++++++++----- .../classes/styles/vector/vector_style.tsx | 40 +++++--------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 2bc819daeea9..98b58def905e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -6,7 +6,8 @@ import _ from 'lodash'; import React from 'react'; -import { Feature } from 'geojson'; +import { Feature, FeatureCollection } from 'geojson'; +import { FeatureIdentifier, Map as MbMap } from 'mapbox-gl'; import { AbstractStyleProperty, IStyleProperty } from './style_property'; import { DEFAULT_SIGMA } from '../vector_style_defaults'; import { @@ -44,20 +45,14 @@ export interface IDynamicStyleProperty extends IStyleProperty { isOrdinal(): boolean; supportsFieldMeta(): boolean; getFieldMetaRequest(): Promise; - supportsMbFeatureState(): boolean; - getMbLookupFunction(): MB_LOOKUP_FUNCTION; pluckOrdinalStyleMetaFromFeatures(features: Feature[]): RangeFieldMeta | null; pluckCategoricalStyleMetaFromFeatures(features: Feature[]): CategoryFieldMeta | null; getValueSuggestions(query: string): Promise; - - // Returns the name that should be used for accessing the data from the mb-style rule - // Depending on - // - whether the field is used for labeling, icon-orientation, or other properties (color, size, ...), `feature-state` and or `get` is used - // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value - // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). - // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. - getMbPropertyName(): string; - getMbPropertyValue(value: RawValue): RawValue; + enrichGeoJsonAndMbFeatureState( + featureCollection: FeatureCollection, + mbMap: MbMap, + mbSourceId: string + ): boolean; } export class DynamicStyleProperty @@ -356,6 +351,12 @@ export class DynamicStyleProperty ); } + // Returns the name that should be used for accessing the data from the mb-style rule + // Depending on + // - whether the field is used for labeling, icon-orientation, or other properties (color, size, ...), `feature-state` and or `get` is used + // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value + // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). + // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. getMbPropertyName() { if (!this._field) { return ''; @@ -385,6 +386,35 @@ export class DynamicStyleProperty // Calling `isOrdinal` would be equivalent. return this.supportsMbFeatureState() ? getNumericalMbFeatureStateValue(rawValue) : rawValue; } + + enrichGeoJsonAndMbFeatureState( + featureCollection: FeatureCollection, + mbMap: MbMap, + mbSourceId: string + ): boolean { + const supportsFeatureState = this.supportsMbFeatureState(); + const featureIdentifier: FeatureIdentifier = { + source: mbSourceId, + id: undefined, + }; + const featureState: Record = {}; + const targetMbName = this.getMbPropertyName(); + for (let i = 0; i < featureCollection.features.length; i++) { + const feature = featureCollection.features[i]; + const rawValue = feature.properties ? feature.properties[this.getFieldName()] : undefined; + const targetMbValue = this.getMbPropertyValue(rawValue); + if (supportsFeatureState) { + featureState[targetMbName] = targetMbValue; // the same value will be potentially overridden multiple times, if the name remains identical + featureIdentifier.id = feature.id; + mbMap.setFeatureState(featureIdentifier, featureState); + } else { + if (feature.properties) { + feature.properties[targetMbName] = targetMbValue; + } + } + } + return supportsFeatureState; + } } export function getNumericalMbFeatureStateValue(value: RawValue) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 5d0d9712ef98..acb158636e0b 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -641,7 +641,7 @@ export class VectorStyle implements IVectorStyle { featureCollection: FeatureCollection, mbMap: MbMap, mbSourceId: string - ) { + ): boolean { if (!featureCollection) { return false; } @@ -651,40 +651,24 @@ export class VectorStyle implements IVectorStyle { return false; } - const tmpFeatureIdentifier: FeatureIdentifier = { - source: '', - id: undefined, - }; - const tmpFeatureState: any = {}; - - for (let i = 0; i < featureCollection.features.length; i++) { - const feature = featureCollection.features[i]; - - for (let j = 0; j < dynamicStyleProps.length; j++) { - const dynamicStyleProp = dynamicStyleProps[j]; - const targetMbName = dynamicStyleProp.getMbPropertyName(); - const rawValue = feature.properties - ? feature.properties[dynamicStyleProp.getFieldName()] - : undefined; - const targetMbValue = dynamicStyleProp.getMbPropertyValue(rawValue); - if (dynamicStyleProp.supportsMbFeatureState()) { - tmpFeatureState[targetMbName] = targetMbValue; // the same value will be potentially overridden multiple times, if the name remains identical - } else { - if (feature.properties) { - feature.properties[targetMbName] = targetMbValue; - } - } + let shouldResetAllData = false; + for (let j = 0; j < dynamicStyleProps.length; j++) { + const dynamicStyleProp = dynamicStyleProps[j]; + const usedFeatureState = dynamicStyleProp.enrichGeoJsonAndMbFeatureState( + featureCollection, + mbMap, + mbSourceId + ); + if (!usedFeatureState) { + shouldResetAllData = true; } - tmpFeatureIdentifier.source = mbSourceId; - tmpFeatureIdentifier.id = feature.id; - mbMap.setFeatureState(tmpFeatureIdentifier, tmpFeatureState); } // returns boolean indicating if styles do not support feature-state and some values are stored in geojson properties // this return-value is used in an optimization for style-updates with mapbox-gl. // `true` indicates the entire data needs to reset on the source (otherwise the style-rules will not be reapplied) // `false` indicates the data does not need to be reset on the store, because styles are re-evaluated if they use featureState - return dynamicStyleProps.some((dynamicStyleProp) => !dynamicStyleProp.supportsMbFeatureState()); + return shouldResetAllData; } arePointsSymbolizedAsCircles() {