[Maps] Introduce typed styles (#49803)

This commit is contained in:
Thomas Neirynck 2019-10-31 14:06:14 -04:00 committed by GitHub
parent 559ac840c5
commit 479177a3ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 522 additions and 268 deletions

View file

@ -7,7 +7,7 @@
import _ from 'lodash';
import { AbstractLayer } from './layer';
import { VectorLayer } from './vector_layer';
import { HeatmapStyle } from './styles/heatmap_style';
import { HeatmapStyle } from './styles/heatmap/heatmap_style';
import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../common/constants';
const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__';//unique name to store scaled value for weighting

View file

@ -6,7 +6,7 @@
import { ESTermSource } from '../sources/es_term_source';
import { VectorStyle } from '../styles/vector_style';
import { VectorStyle } from '../styles/vector/vector_style';
export class InnerJoin {

View file

@ -14,8 +14,8 @@ import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
import { tabifyAggResponse } from 'ui/agg_response/tabify';
import { convertToGeoJson } from './convert_to_geojson';
import { VectorStyle } from '../../styles/vector_style';
import { vectorStyles } from '../../styles/vector_style_defaults';
import { VectorStyle } from '../../styles/vector/vector_style';
import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { RENDER_AS } from './render_as';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';

View file

@ -11,8 +11,8 @@ import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
import { VectorLayer } from '../../vector_layer';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
import { VectorStyle } from '../../styles/vector_style';
import { vectorStyles } from '../../styles/vector_style_defaults';
import { VectorStyle } from '../../styles/vector/vector_style';
import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { i18n } from '@kbn/i18n';
import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW } from '../../../../common/constants';
import { getDataSourceLabel } from '../../../../common/i18n_getters';

View file

@ -7,7 +7,7 @@
import { VectorLayer } from '../vector_layer';
import { TooltipProperty } from '../tooltips/tooltip_property';
import { VectorStyle } from '../styles/vector_style';
import { VectorStyle } from '../styles/vector/vector_style';
import { AbstractSource } from './source';
import * as topojson from 'topojson-client';
import _ from 'lodash';

View file

@ -1,3 +1,3 @@
@import './components/color_gradient';
@import './components/static_dynamic_style_row';
@import './components/vector/color/color_stops';
@import './vector/components/color/color_stops';

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import { VectorStyle } from '../vector_style';
import { VectorStyle } from '../vector/vector_style';
import _ from 'lodash';
import { i18n } from '@kbn/i18n';

View file

@ -8,7 +8,7 @@ import React from 'react';
import { EuiFormRow, EuiSuperSelect } from '@elastic/eui';
import { COLOR_GRADIENTS } from '../../color_utils';
import { ColorGradient } from '../color_gradient';
import { ColorGradient } from '../../components/color_gradient';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,

View file

@ -7,8 +7,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { ColorGradient } from '../../color_gradient';
import { StyleLegendRow } from '../../style_legend_row';
import { ColorGradient } from '../../../components/color_gradient';
import { StyleLegendRow } from '../../../components/style_legend_row';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,

View file

@ -5,12 +5,12 @@
*/
import React from 'react';
import { GRID_RESOLUTION } from '../grid_resolution';
import { AbstractStyle } from './abstract_style';
import { HeatmapStyleEditor } from './components/heatmap/heatmap_style_editor';
import { HeatmapLegend } from './components/heatmap/legend/heatmap_legend';
import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap/heatmap_constants';
import { getColorRampStops } from './color_utils';
import { GRID_RESOLUTION } from '../../grid_resolution';
import { AbstractStyle } from '../abstract_style';
import { HeatmapStyleEditor } from './components/heatmap_style_editor';
import { HeatmapLegend } from './components/legend/heatmap_legend';
import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap_constants';
import { getColorRampStops } from '../color_utils';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';

View file

@ -6,7 +6,7 @@
import React from 'react';
import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicColorSelection } from './dynamic_color_selection';
import { StaticColorSelection } from './static_color_selection';
import { getVectorStyleLabel } from '../get_vector_style_label';

View file

@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import { vectorStyles } from '../../vector_style_defaults';
import { vectorStyles } from '../vector_style_defaults';
export function getVectorStyleLabel(styleName) {
switch (styleName) {

View file

@ -9,12 +9,12 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
import { VectorStyle } from '../../../vector_style';
import { ColorGradient } from '../../color_gradient';
import { VectorStyle } from '../../vector_style';
import { ColorGradient } from '../../../components/color_gradient';
import { CircleIcon } from './circle_icon';
import { getVectorStyleLabel } from '../get_vector_style_label';
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
import { StyleLegendRow } from '../../style_legend_row';
import { StyleLegendRow } from '../../../components/style_legend_row';
function getLineWidthIcons() {
const defaultStyle = {

View file

@ -7,7 +7,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { getMakiSymbolSvg, styleSvg, buildSrcUrl } from '../../../symbol_utils';
import { getMakiSymbolSvg, styleSvg, buildSrcUrl } from '../../symbol_utils';
export class SymbolIcon extends Component {

View file

@ -12,7 +12,7 @@ import { CircleIcon } from './circle_icon';
import { LineIcon } from './line_icon';
import { PolygonIcon } from './polygon_icon';
import { SymbolIcon } from './symbol_icon';
import { VectorStyle } from '../../../vector_style';
import { VectorStyle } from '../../vector_style';
import { getColorRampCenterColor } from '../../../color_utils';
export class VectorIcon extends Component {

View file

@ -8,7 +8,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { VectorIcon } from './vector_icon';
import { VectorStyle } from '../../../vector_style';
import { VectorStyle } from '../../vector_style';
let isPointsOnly = false;
let isLinesOnly = false;

View file

@ -6,7 +6,7 @@
import React from 'react';
import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicOrientationSelection } from './dynamic_orientation_selection';
import { StaticOrientationSelection } from './static_orientation_selection';
import { i18n } from '@kbn/i18n';

View file

@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ValidatedDualRange } from 'ui/validated_range';
import { DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE } from '../../../vector_style_defaults';
import { DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE } from '../../vector_style_defaults';
import { i18n } from '@kbn/i18n';
export function SizeRangeSelector({ minSize, maxSize, onChange, ...rest }) {

View file

@ -6,7 +6,7 @@
import React from 'react';
import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicSizeSelection } from './dynamic_size_selection';
import { StaticSizeSelection } from './static_size_selection';
import { getVectorStyleLabel } from '../get_vector_style_label';

View file

@ -16,12 +16,12 @@ import {
getDefaultDynamicProperties,
getDefaultStaticProperties,
vectorStyles,
} from '../../vector_style_defaults';
} from '../vector_style_defaults';
import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../color_utils';
import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types';
import { SYMBOLIZE_AS_ICON } from '../../vector_constants';
import { SYMBOLIZE_AS_ICON } from '../vector_constants';
import { i18n } from '@kbn/i18n';
import { SYMBOL_OPTIONS } from '../../symbol_utils';
import { SYMBOL_OPTIONS } from '../symbol_utils';
import { EuiSpacer, EuiButtonGroup } from '@elastic/eui';

View file

@ -16,7 +16,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../../vector_constants';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../vector_constants';
import { SymbolIcon } from './legend/symbol_icon';
const SYMBOLIZE_AS_OPTIONS = [

View file

@ -7,7 +7,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../../vector_constants';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../vector_constants';
import { VectorStyleSymbolEditor } from './vector_style_symbol_editor';
const symbolOptions = [

View file

@ -0,0 +1,105 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { DynamicStyleProperty } from './dynamic_style_property';
import _ from 'lodash';
import { getComputedFieldName } from '../style_util';
import { getColorRampStops } from '../../color_utils';
export class DynamicColorProperty extends DynamicStyleProperty {
syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
const color = this._getMbColor();
mbMap.setPaintProperty(mbLayerId, 'circle-color', color);
mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
}
syncIconColorWithMb(mbLayerId, mbMap) {
const color = this._getMbColor();
mbMap.setPaintProperty(mbLayerId, 'icon-color', color);
}
syncHaloBorderColorWithMb(mbLayerId, mbMap) {
const color = this._getMbColor();
mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', color);
}
syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
const color = this._getMbColor();
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
}
syncFillColorWithMb(mbLayerId, mbMap, alpha) {
const color = this._getMbColor();
mbMap.setPaintProperty(mbLayerId, 'fill-color', color);
mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
}
syncLineColorWithMb(mbLayerId, mbMap, alpha) {
const color = this._getMbColor();
mbMap.setPaintProperty(mbLayerId, 'line-color', color);
mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
}
_getMbColor() {
const isDynamicConfigComplete = _.has(this._options, 'field.name') && _.has(this._options, 'color');
if (!isDynamicConfigComplete) {
return null;
}
if (this._options.useCustomColorRamp && (!this._options.customColorRamp || !this._options.customColorRamp.length)) {
return null;
}
return this._getMBDataDrivenColor({
targetName: getComputedFieldName(this._styleName, this._options.field.name),
colorStops: this._getMBColorStops(),
isSteps: this._options.useCustomColorRamp,
});
}
_getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
if (isSteps) {
const firstStopValue = colorStops[0];
const lessThenFirstStopValue = firstStopValue - 1;
return [
'step',
['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
...colorStops
];
}
return [
'interpolate',
['linear'],
['coalesce', ['feature-state', targetName], -1],
-1, 'rgba(0,0,0,0)',
...colorStops
];
}
_getMBColorStops() {
if (this._options.useCustomColorRamp) {
return this._options.customColorRamp.reduce((accumulatedStops, nextStop) => {
return [...accumulatedStops, nextStop.stop, nextStop.color];
}, []);
}
return getColorRampStops(this._options.color);
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { DynamicStyleProperty } from './dynamic_style_property';
import { getComputedFieldName } from '../style_util';
import { vectorStyles } from '../vector_style_defaults';
export class DynamicOrientationProperty extends DynamicStyleProperty {
syncIconRotationWithMb(symbolLayerId, mbMap) {
if (this._options.field && this._options.field.name) {
const targetName = getComputedFieldName(vectorStyles.ICON_ORIENTATION, this._options.field.name);
// Using property state instead of feature-state because layout properties do not support feature-state
mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]);
} else {
mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0);
}
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { DynamicStyleProperty } from './dynamic_style_property';
import { getComputedFieldName } from '../style_util';
import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
import { vectorStyles } from '../vector_style_defaults';
import _ from 'lodash';
export class DynamicSizeProperty extends DynamicStyleProperty {
syncHaloWidthWithMb(mbLayerId, mbMap) {
const haloWidth = this._getMbSize();
mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth);
}
syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
if (this._isSizeDynamicConfigComplete(this._options)) {
const iconPixels = this._options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
? LARGE_MAKI_ICON_SIZE
: SMALL_MAKI_ICON_SIZE;
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
const halfIconPixels = iconPixels / 2;
const targetName = getComputedFieldName(vectorStyles.ICON_SIZE, this._options.field.name);
// Using property state instead of feature-state because layout properties do not support feature-state
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
'interpolate',
['linear'],
['coalesce', ['get', targetName], 0],
0, this._options.minSize / halfIconPixels,
1, this._options.maxSize / halfIconPixels
]);
} else {
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', null);
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', null);
}
}
syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
const lineWidth = this._getMbSize();
mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
}
syncCircleRadiusWithMb(mbLayerId, mbMap) {
const circleRadius = this._getMbSize();
mbMap.setPaintProperty(mbLayerId, 'circle-radius', circleRadius);
}
syncLineWidthWithMb(mbLayerId, mbMap) {
const lineWidth = this._getMbSize();
mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth);
}
_getMbSize() {
if (this._isSizeDynamicConfigComplete(this._options)) {
return this._getMbDataDrivenSize({
targetName: getComputedFieldName(this._styleName, this._options.field.name),
minSize: this._options.minSize,
maxSize: this._options.maxSize,
});
}
return null;
}
_getMbDataDrivenSize({ targetName, minSize, maxSize }) {
return [
'interpolate',
['linear'],
['coalesce', ['feature-state', targetName], 0],
0, minSize,
1, maxSize
];
}
_isSizeDynamicConfigComplete() {
return this._options.field && this._options.field.name && _.has(this._options, 'minSize') && _.has(this._options, 'maxSize');
}
}

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { AbstractStyleProperty } from './style_property';
export class DynamicStyleProperty extends AbstractStyleProperty {
static type = 'DYNAMIC';
}

View file

@ -0,0 +1,41 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { StaticStyleProperty } from './static_style_property';
export class StaticColorProperty extends StaticStyleProperty {
syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
mbMap.setPaintProperty(mbLayerId, 'circle-color', this._options.color);
mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
}
syncFillColorWithMb(mbLayerId, mbMap, alpha) {
mbMap.setPaintProperty(mbLayerId, 'fill-color', this._options.color);
mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
}
syncIconColorWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'icon-color', this._options.color);
}
syncHaloBorderColorWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', this._options.color);
}
syncLineColorWithMb(mbLayerId, mbMap, alpha) {
mbMap.setPaintProperty(mbLayerId, 'line-color', this._options.color);
mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
}
syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', this._options.color);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { StaticStyleProperty } from './static_style_property';
export class StaticOrientationProperty extends StaticStyleProperty {
constructor(options, styleName) {
if (typeof options.orientation !== 'number') {
super({ orientation: 0 }, styleName);
} else {
super(options, styleName);
}
}
syncIconRotationWithMb(symbolLayerId, mbMap) {
mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', this._options.orientation);
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { StaticStyleProperty } from './static_style_property';
import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
export class StaticSizeProperty extends StaticStyleProperty {
constructor(options, styleName) {
if (typeof options.size !== 'number') {
super({ size: 1 }, styleName);
} else {
super(options, styleName);
}
}
syncHaloWidthWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', this._options.size);
}
syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
const iconPixels = this._size >= HALF_LARGE_MAKI_ICON_SIZE ? LARGE_MAKI_ICON_SIZE : SMALL_MAKI_ICON_SIZE;
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
const halfIconPixels = iconPixels / 2;
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels);
}
syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', this._options.size);
}
syncCircleRadiusWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'circle-radius', this._options.size);
}
syncLineWidthWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'line-width', this._options.size);
}
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { AbstractStyleProperty } from './style_property';
export class StaticStyleProperty extends AbstractStyleProperty {
static type = 'STATIC';
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export class AbstractStyleProperty {
constructor(options, styleName) {
this._options = options;
this._styleName = styleName;
}
}

View file

@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export function getComputedFieldName(styleName, fieldName) {
return `${getComputedFieldNamePrefix(fieldName)}__${styleName}`;
}
export function getComputedFieldNamePrefix(fieldName) {
return `__kbn__dynamic__${fieldName}`;
}

View file

@ -6,7 +6,7 @@
import maki from '@elastic/maki';
import xml2js from 'xml2js';
import { parseXmlString } from '../../../common/parse_xml_string';
import { parseXmlString } from '../../../../common/parse_xml_string';
export const LARGE_MAKI_ICON_SIZE = 15;
const LARGE_MAKI_ICON_SIZE_AS_STRING = LARGE_MAKI_ICON_SIZE.toString();

View file

@ -7,34 +7,36 @@
import _ from 'lodash';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { getColorRampStops } from './color_utils';
import { VectorStyleEditor } from './components/vector/vector_style_editor';
import { VectorStyleEditor } from './components/vector_style_editor';
import { getDefaultProperties, vectorStyles } from './vector_style_defaults';
import { AbstractStyle } from './abstract_style';
import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE } from '../../../common/constants';
import { VectorIcon } from './components/vector/legend/vector_icon';
import { VectorStyleLegend } from './components/vector/legend/vector_style_legend';
import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
import { AbstractStyle } from '../abstract_style';
import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE } from '../../../../common/constants';
import { VectorIcon } from './components/legend/vector_icon';
import { VectorStyleLegend } from './components/legend/vector_style_legend';
import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from './vector_constants';
import {
getMakiSymbolAnchor,
LARGE_MAKI_ICON_SIZE,
SMALL_MAKI_ICON_SIZE,
HALF_LARGE_MAKI_ICON_SIZE
} from './symbol_utils';
import { getMakiSymbolAnchor } from './symbol_utils';
import { getComputedFieldName, getComputedFieldNamePrefix } from './style_util';
import { StaticStyleProperty } from './properties/static_style_property';
import { DynamicStyleProperty } from './properties/dynamic_style_property';
import { DynamicSizeProperty } from './properties/dynamic_size_property';
import { StaticSizeProperty } from './properties/static_size_property';
import { StaticColorProperty } from './properties/static_color_property';
import { DynamicColorProperty } from './properties/dynamic_color_property';
import { StaticOrientationProperty } from './properties/static_orientation_property';
import { DynamicOrientationProperty } from './properties/dynamic_orientation_property';
const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING];
const POLYGONS = [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON];
export class VectorStyle extends AbstractStyle {
static type = 'VECTOR';
static STYLE_TYPE = { 'DYNAMIC': 'DYNAMIC', 'STATIC': 'STATIC' };
static STYLE_TYPE = { 'DYNAMIC': DynamicStyleProperty.type, 'STATIC': StaticStyleProperty.type };
static getComputedFieldName(styleName, fieldName) {
return `${VectorStyle.getComputedFieldNamePrefix(fieldName)}__${styleName}`;
}
static getComputedFieldNamePrefix(fieldName) {
return `__kbn__dynamic__${fieldName}`;
}
static getComputedFieldName = getComputedFieldName;
static getComputedFieldNamePrefix = getComputedFieldNamePrefix;
constructor(descriptor = {}, source) {
super();
@ -43,6 +45,13 @@ export class VectorStyle extends AbstractStyle {
...descriptor,
...VectorStyle.createDescriptor(descriptor.properties),
};
this._lineColorStyleProperty = this._makeColorProperty(this._descriptor.properties[vectorStyles.LINE_COLOR], vectorStyles.LINE_COLOR);
this._fillColorStyleProperty = this._makeColorProperty(this._descriptor.properties[vectorStyles.FILL_COLOR], vectorStyles.FILL_COLOR);
this._lineWidthStyleProperty = this._makeSizeProperty(this._descriptor.properties[vectorStyles.LINE_WIDTH], vectorStyles.LINE_WIDTH);
this._iconSizeStyleProperty = this._makeSizeProperty(this._descriptor.properties[vectorStyles.ICON_SIZE], vectorStyles.ICON_SIZE);
// eslint-disable-next-line max-len
this._iconOrientationProperty = this._makeOrientationProperty(this._descriptor.properties[vectorStyles.ICON_ORIENTATION], vectorStyles.ICON_ORIENTATION);
}
static createDescriptor(properties = {}) {
@ -168,13 +177,13 @@ export class VectorStyle extends AbstractStyle {
let hasPolygons = false;
for (let i = 0; i < features.length; i++) {
const feature = features[i];
if (!hasPoints && [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT].includes(feature.geometry.type)) {
if (!hasPoints && POINTS.includes(feature.geometry.type)) {
hasPoints = true;
}
if (!hasLines && [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING].includes(feature.geometry.type)) {
if (!hasLines && LINES.includes(feature.geometry.type)) {
hasLines = true;
}
if (!hasPolygons && [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON].includes(feature.geometry.type)) {
if (!hasPolygons && POLYGONS.includes(feature.geometry.type)) {
hasPolygons = true;
}
@ -430,210 +439,72 @@ export class VectorStyle extends AbstractStyle {
return hasGeoJsonProperties;
}
_getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
if (isSteps) {
const firstStopValue = colorStops[0];
const lessThenFirstStopValue = firstStopValue - 1;
return [
'step',
['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
...colorStops
];
}
return [
'interpolate',
['linear'],
['coalesce', ['feature-state', targetName], -1],
-1, 'rgba(0,0,0,0)',
...colorStops
];
}
_getMbDataDrivenSize({ targetName, minSize, maxSize }) {
return [
'interpolate',
['linear'],
['coalesce', ['feature-state', targetName], 0],
0, minSize,
1, maxSize
];
}
_getMBColor(styleName, styleDescriptor) {
const isStatic = styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC;
if (isStatic) {
return _.get(styleDescriptor, 'options.color', null);
}
const isDynamicConfigComplete = _.has(styleDescriptor, 'options.field.name')
&& _.has(styleDescriptor, 'options.color');
if (!isDynamicConfigComplete) {
return null;
}
if (styleDescriptor.options.useCustomColorRamp &&
(!styleDescriptor.options.customColorRamp ||
!styleDescriptor.options.customColorRamp.length)) {
return null;
}
return this._getMBDataDrivenColor({
targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
colorStops: this._getMBColorStops(styleDescriptor),
isSteps: styleDescriptor.options.useCustomColorRamp,
});
}
_getMBColorStops(styleDescriptor) {
if (styleDescriptor.options.useCustomColorRamp) {
return styleDescriptor.options.customColorRamp.reduce((accumulatedStops, nextStop) => {
return [...accumulatedStops, nextStop.stop, nextStop.color];
}, []);
}
return getColorRampStops(styleDescriptor.options.color);
}
_isSizeDynamicConfigComplete(styleDescriptor) {
return _.has(styleDescriptor, 'options.field.name')
&& _.has(styleDescriptor, 'options.minSize')
&& _.has(styleDescriptor, 'options.maxSize');
}
_getMbSize(styleName, styleDescriptor) {
if (styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC) {
return styleDescriptor.options.size;
}
if (this._isSizeDynamicConfigComplete(styleDescriptor)) {
return this._getMbDataDrivenSize({
targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
minSize: styleDescriptor.options.minSize,
maxSize: styleDescriptor.options.maxSize,
});
}
return null;
}
setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
if (this._descriptor.properties.fillColor) {
const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
mbMap.setPaintProperty(fillLayerId, 'fill-color', color);
mbMap.setPaintProperty(fillLayerId, 'fill-opacity', alpha);
} else {
mbMap.setPaintProperty(fillLayerId, 'fill-color', null);
mbMap.setPaintProperty(fillLayerId, 'fill-opacity', 0);
}
if (this._descriptor.properties.lineColor) {
const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
mbMap.setPaintProperty(lineLayerId, 'line-color', color);
mbMap.setPaintProperty(lineLayerId, 'line-opacity', alpha);
} else {
mbMap.setPaintProperty(lineLayerId, 'line-color', null);
mbMap.setPaintProperty(lineLayerId, 'line-opacity', 0);
}
if (this._descriptor.properties.lineWidth) {
const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
mbMap.setPaintProperty(lineLayerId, 'line-width', lineWidth);
} else {
mbMap.setPaintProperty(lineLayerId, 'line-width', 0);
}
}
setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
if (this._descriptor.properties.fillColor) {
const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
mbMap.setPaintProperty(pointLayerId, 'circle-color', color);
mbMap.setPaintProperty(pointLayerId, 'circle-opacity', alpha);
} else {
mbMap.setPaintProperty(pointLayerId, 'circle-color', null);
mbMap.setPaintProperty(pointLayerId, 'circle-opacity', 0);
}
if (this._descriptor.properties.lineColor) {
const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
} else {
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', null);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', 0);
}
if (this._descriptor.properties.lineWidth) {
const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', lineWidth);
} else {
mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', 0);
}
if (this._descriptor.properties.iconSize) {
const iconSize = this._getMbSize(vectorStyles.ICON_SIZE, this._descriptor.properties.iconSize);
mbMap.setPaintProperty(pointLayerId, 'circle-radius', iconSize);
} else {
mbMap.setPaintProperty(pointLayerId, 'circle-radius', 0);
}
}
async setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
const symbolId = this._descriptor.properties.symbol.options.symbolId;
mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
const haloColor = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
const haloWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
// icon-color is only supported on SDF icons.
mbMap.setPaintProperty(symbolLayerId, 'icon-color', color);
mbMap.setPaintProperty(symbolLayerId, 'icon-halo-color', haloColor);
mbMap.setPaintProperty(symbolLayerId, 'icon-halo-width', haloWidth);
mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
// circle sizing is by radius
// to make icons be similiar in size to circles then have to deal with icon in half width measurements
const iconSize = this._descriptor.properties.iconSize;
if (iconSize.type === VectorStyle.STYLE_TYPE.STATIC) {
const iconPixels = iconSize.options.size >= HALF_LARGE_MAKI_ICON_SIZE
? LARGE_MAKI_ICON_SIZE
: SMALL_MAKI_ICON_SIZE;
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
const halfIconPixels = iconPixels / 2;
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', iconSize.options.size / halfIconPixels);
} else if (this._isSizeDynamicConfigComplete(iconSize)) {
const iconPixels = iconSize.options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
? LARGE_MAKI_ICON_SIZE
: SMALL_MAKI_ICON_SIZE;
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
const halfIconPixels = iconPixels / 2;
const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_SIZE, iconSize.options.field.name);
// Using property state instead of feature-state because layout properties do not support feature-state
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
'interpolate',
['linear'],
['coalesce', ['get', targetName], 0],
0, iconSize.options.minSize / halfIconPixels,
1, iconSize.options.maxSize / halfIconPixels
]);
}
const iconOrientation = this._descriptor.properties.iconOrientation;
if (iconOrientation.type === VectorStyle.STYLE_TYPE.STATIC) {
mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', iconOrientation.options.orientation);
} else if (_.has(iconOrientation, 'options.field.name')) {
const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_ORIENTATION, iconOrientation.options.field.name);
// Using property state instead of feature-state because layout properties do not support feature-state
mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', [
'coalesce', ['get', targetName], 0
]);
}
}
arePointsSymbolizedAsCircles() {
return this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE;
}
setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
this._fillColorStyleProperty.syncFillColorWithMb(fillLayerId, mbMap, alpha);
this._lineColorStyleProperty.syncLineColorWithMb(lineLayerId, mbMap, alpha);
this._lineWidthStyleProperty.syncLineWidthWithMb(lineLayerId, mbMap);
}
setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
this._fillColorStyleProperty.syncCircleColorWithMb(pointLayerId, mbMap, alpha);
this._lineColorStyleProperty.syncCircleStrokeWithMb(pointLayerId, mbMap, alpha);
this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap);
this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap);
}
setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
const symbolId = this._descriptor.properties.symbol.options.symbolId;
mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
// icon-color is only supported on SDF icons.
this._fillColorStyleProperty.syncIconColorWithMb(symbolLayerId, mbMap);
this._lineColorStyleProperty.syncHaloBorderColorWithMb(symbolLayerId, mbMap);
this._lineWidthStyleProperty.syncHaloWidthWithMb(symbolLayerId, mbMap);
this._iconSizeStyleProperty.syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId);
this._iconOrientationProperty.syncIconRotationWithMb(symbolLayerId, mbMap);
}
_makeSizeProperty(descriptor, styleName) {
if (!descriptor || !descriptor.options) {
return new StaticSizeProperty({ size: 0 }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticSizeProperty(descriptor.options, styleName);
} else if (descriptor.type === DynamicStyleProperty.type) {
return new DynamicSizeProperty(descriptor.options, styleName);
} else {
throw new Error(`${descriptor} not implemented`);
}
}
_makeColorProperty(descriptor, styleName) {
if (!descriptor || !descriptor.options) {
return new StaticColorProperty({ color: null }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticColorProperty(descriptor.options, styleName);
} else if (descriptor.type === DynamicStyleProperty.type) {
return new DynamicColorProperty(descriptor.options, styleName);
} else {
throw new Error(`${descriptor} not implemented`);
}
}
_makeOrientationProperty(descriptor, styleName) {
if (!descriptor || !descriptor.options) {
return new StaticOrientationProperty({ orientation: 0 }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticOrientationProperty(descriptor.options, styleName);
} else if (descriptor.type === DynamicStyleProperty.type) {
return new DynamicOrientationProperty(descriptor.options, styleName);
} else {
throw new Error(`${descriptor} not implemented`);
}
}
}

View file

@ -5,8 +5,8 @@
*/
import { VectorStyle } from './vector_style';
import { DataRequest } from '../util/data_request';
import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
import { DataRequest } from '../../util/data_request';
import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
describe('getDescriptorWithMissingStylePropsRemoved', () => {
const fieldName = 'doIStillExist';

View file

@ -10,7 +10,7 @@ import {
COLOR_GRADIENTS,
DEFAULT_FILL_COLORS,
DEFAULT_LINE_COLORS
} from './color_utils';
} from '../color_utils';
const DEFAULT_ICON = 'airfield';

View file

@ -7,7 +7,7 @@
import turf from 'turf';
import React from 'react';
import { AbstractLayer } from './layer';
import { VectorStyle } from './styles/vector_style';
import { VectorStyle } from './styles/vector/vector_style';
import { InnerJoin } from './joins/inner_join';
import {
GEO_JSON_TYPE,

View file

@ -11,8 +11,8 @@ import { VectorTileLayer } from '../layers/vector_tile_layer';
import { VectorLayer } from '../layers/vector_layer';
import { HeatmapLayer } from '../layers/heatmap_layer';
import { ALL_SOURCES } from '../layers/sources/all_sources';
import { VectorStyle } from '../layers/styles/vector_style';
import { HeatmapStyle } from '../layers/styles/heatmap_style';
import { VectorStyle } from '../layers/styles/vector/vector_style';
import { HeatmapStyle } from '../layers/styles/heatmap/heatmap_style';
import { timefilter } from 'ui/timefilter';
import { getInspectorAdapters } from '../reducers/non_serializable_instances';
import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from '../reducers/util';