diff --git a/docs/maps/vector-style-properties.asciidoc b/docs/maps/vector-style-properties.asciidoc
index f51632218add1..5656a7f04d0e3 100644
--- a/docs/maps/vector-style-properties.asciidoc
+++ b/docs/maps/vector-style-properties.asciidoc
@@ -8,32 +8,52 @@ Point, polygon, and line features support different styling properties.
[[point-style-properties]]
==== Point style properties
+You can add text labels to your Point features by configuring label style properties.
+
+[cols="2*"]
+|===
+|*Label*
+|Specifies label content.
+|*Label color*
+|The text color.
+|*Label size*
+|The size of the text font, in pixels.
+|===
+
You can symbolize Point features as *Circle markers* or *Icons*.
Use *Circle marker* to symbolize Points as circles.
-*Fill color*:: The fill color of the point features.
-
-*Border color*:: The border color of the point features.
-
-*Border width*:: The border width of the point features.
-
-*Symbol size*:: The radius of the symbol size, in pixels.
+[cols="2*"]
+|===
+|*Border color*
+|The border color of the point features.
+|*Border width*
+|The border width of the point features.
+|*Fill color*
+|The fill color of the point features.
+|*Symbol size*
+|The radius of the symbol size, in pixels.
+|===
Use *Icon* to symbolize Points as icons.
-*Fill color*:: The fill color of the point features.
-
-*Border color*:: The border color of the point features.
-
-*Border width*:: The border width of the point features.
+[cols="2*"]
+|===
+|*Border color*
+|The border color of the point features.
+|*Border width*
+|The border width of the point features.
+|*Fill color*
+|The fill color of the point features.
+|*Symbol orientation*
+|The symbol orientation rotating the icon clockwise.
+|*Symbol size*
+|The radius of the symbol size, in pixels.
+|===
-*Symbol orientation*:: The symbol orientation rotating the icon clockwise.
-
-*Symbol size*:: The radius of the symbol size, in pixels.
-+
Available icons
-+
+
[role="screenshot"]
image::maps/images/maki-icons.png[]
@@ -42,17 +62,25 @@ image::maps/images/maki-icons.png[]
[[polygon-style-properties]]
==== Polygon style properties
-*Fill color*:: The fill color of the polygon features.
-
-*Border color*:: The border color of the polygon features.
-
-*Border width*:: The border width of the polygon features.
+[cols="2*"]
+|===
+|*Border color*
+|The border color of the polygon features.
+|*Border width*
+|The border width of the polygon features.
+|*Fill color*
+|The fill color of the polygon features.
+|===
[float]
[[line-style-properties]]
==== Line style properties
-*Border color*:: The color of the line features.
-
-*Border width*:: The width of the line features.
+[cols="2*"]
+|===
+|*Border color*
+|The color of the line features.
+|*Border width*
+|The width of the line features.
+|===
diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js
index 2890b75172fb0..21c5f15fb6122 100644
--- a/x-pack/legacy/plugins/maps/public/layers/layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/layer.js
@@ -344,6 +344,10 @@ export class AbstractLayer {
return [];
}
+ async getFields() {
+ return [];
+ }
+
syncVisibilityWithMb(mbMap, mbLayerId) {
mbMap.setLayoutProperty(mbLayerId, 'visibility', this.isVisible() ? 'visible' : 'none');
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
index d8960ae1f6a04..d852332ac2f84 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
@@ -124,6 +124,24 @@ export class ESSearchSource extends AbstractESSource {
}
}
+ async getFields() {
+ try {
+ const indexPattern = await this.getIndexPattern();
+ return indexPattern.fields
+ .filter(field => {
+ // Ensure fielddata is enabled for field.
+ // Search does not request _source
+ return field.aggregatable;
+ })
+ .map(field => {
+ return this.createField({ fieldName: field.name });
+ });
+ } catch (error) {
+ // failed index-pattern retrieval will show up as error-message in the layer-toc-entry
+ return [];
+ }
+ }
+
getFieldNames() {
return [this._descriptor.geoField];
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
index 814cbffc7bfe3..bf7267e9c5858 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
@@ -103,6 +103,10 @@ export class AbstractVectorSource extends AbstractSource {
return [];
}
+ async getFields() {
+ return [...(await this.getDateFields()), ...(await this.getNumberFields())];
+ }
+
async getLeftJoinFields() {
return [];
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js
index 2db92ba7f9337..84327635f2b65 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js
@@ -12,7 +12,7 @@ import { FieldSelect, fieldShape } from '../field_select';
import { ColorRampSelect } from './color_ramp_select';
import { EuiSpacer } from '@elastic/eui';
-export function DynamicColorSelection({ ordinalFields, onChange, styleOptions }) {
+export function DynamicColorSelection({ fields, onChange, styleOptions }) {
const onFieldChange = ({ field }) => {
onChange({ ...styleOptions, field });
};
@@ -32,7 +32,7 @@ export function DynamicColorSelection({ ordinalFields, onChange, styleOptions })
/>
{
+ onChange({ ...styleOptions, field });
+ };
+
+ return (
+
+ );
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/static_label_selector.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/static_label_selector.js
new file mode 100644
index 0000000000000..ea296a3312799
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/static_label_selector.js
@@ -0,0 +1,28 @@
+/*
+ * 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 React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiFieldText } from '@elastic/eui';
+
+export function StaticLabelSelector({ onChange, styleOptions }) {
+ const onValueChange = event => {
+ onChange({ value: event.target.value });
+ };
+
+ return (
+
+ );
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_editor.js
new file mode 100644
index 0000000000000..6bca56425d38d
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_editor.js
@@ -0,0 +1,21 @@
+/*
+ * 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 React from 'react';
+
+import { StaticDynamicStyleRow } from '../static_dynamic_style_row';
+import { DynamicLabelSelector } from './dynamic_label_selector';
+import { StaticLabelSelector } from './static_label_selector';
+
+export function VectorStyleLabelEditor(props) {
+ return (
+
+ );
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js
index 6df3283737c73..8ad3916ac6509 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js
@@ -10,14 +10,14 @@ import PropTypes from 'prop-types';
import { dynamicOrientationShape } from '../style_option_shapes';
import { FieldSelect, fieldShape } from '../field_select';
-export function DynamicOrientationSelection({ ordinalFields, styleOptions, onChange }) {
+export function DynamicOrientationSelection({ fields, styleOptions, onChange }) {
const onFieldChange = ({ field }) => {
onChange({ ...styleOptions, field });
};
return (
{
onChange({ ...styleOptions, field });
};
@@ -32,7 +32,7 @@ export function DynamicSizeSelection({ ordinalFields, styleOptions, onChange })
/>
0;
+ return this.props.fields.length > 0;
}
_isDynamic() {
@@ -78,7 +78,7 @@ export class StaticDynamicStyleRow extends Component {
return (
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
index 43dd7b1b2d032..44f630db9d890 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
@@ -11,6 +11,7 @@ import chrome from 'ui/chrome';
import { VectorStyleColorEditor } from './color/vector_style_color_editor';
import { VectorStyleSizeEditor } from './size/vector_style_size_editor';
import { VectorStyleSymbolEditor } from './vector_style_symbol_editor';
+import { VectorStyleLabelEditor } from './label/vector_style_label_editor';
import { OrientationEditor } from './orientation/orientation_editor';
import { getDefaultDynamicProperties, getDefaultStaticProperties } from '../vector_style_defaults';
import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../color_utils';
@@ -25,6 +26,7 @@ export class VectorStyleEditor extends Component {
state = {
dateFields: [],
numberFields: [],
+ fields: [],
defaultDynamicProperties: getDefaultDynamicProperties(),
defaultStaticProperties: getDefaultStaticProperties(),
supportedFeatures: undefined,
@@ -37,16 +39,16 @@ export class VectorStyleEditor extends Component {
componentDidMount() {
this._isMounted = true;
- this._loadOrdinalFields();
+ this._loadFields();
this._loadSupportedFeatures();
}
componentDidUpdate() {
- this._loadOrdinalFields();
+ this._loadFields();
this._loadSupportedFeatures();
}
- async _loadOrdinalFields() {
+ async _loadFields() {
const getFieldMeta = async field => {
return {
label: await field.getLabel(),
@@ -54,21 +56,27 @@ export class VectorStyleEditor extends Component {
origin: field.getOrigin(),
};
};
+
const dateFields = await this.props.layer.getDateFields();
const dateFieldPromises = dateFields.map(getFieldMeta);
const dateFieldsArray = await Promise.all(dateFieldPromises);
-
if (this._isMounted && !_.isEqual(dateFieldsArray, this.state.dateFields)) {
this.setState({ dateFields: dateFieldsArray });
}
const numberFields = await this.props.layer.getNumberFields();
const numberFieldPromises = numberFields.map(getFieldMeta);
-
const numberFieldsArray = await Promise.all(numberFieldPromises);
if (this._isMounted && !_.isEqual(numberFieldsArray, this.state.numberFields)) {
this.setState({ numberFields: numberFieldsArray });
}
+
+ const fields = await this.props.layer.getFields();
+ const fieldPromises = fields.map(getFieldMeta);
+ const fieldsArray = await Promise.all(fieldPromises);
+ if (this._isMounted && !_.isEqual(fieldsArray, this.state.fields)) {
+ this.setState({ fields: fieldsArray });
+ }
}
async _loadSupportedFeatures() {
@@ -126,7 +134,7 @@ export class VectorStyleEditor extends Component {
swatches={DEFAULT_FILL_COLORS}
handlePropertyChange={this.props.handlePropertyChange}
styleProperty={this.props.styleProperties.fillColor}
- ordinalFields={this._getOrdinalFields()}
+ fields={this._getOrdinalFields()}
defaultStaticStyleOptions={this.state.defaultStaticProperties.fillColor.options}
defaultDynamicStyleOptions={this.state.defaultDynamicProperties.fillColor.options}
/>
@@ -139,7 +147,7 @@ export class VectorStyleEditor extends Component {
swatches={DEFAULT_LINE_COLORS}
handlePropertyChange={this.props.handlePropertyChange}
styleProperty={this.props.styleProperties.lineColor}
- ordinalFields={this._getOrdinalFields()}
+ fields={this._getOrdinalFields()}
defaultStaticStyleOptions={this.state.defaultStaticProperties.lineColor.options}
defaultDynamicStyleOptions={this.state.defaultDynamicProperties.lineColor.options}
/>
@@ -151,7 +159,7 @@ export class VectorStyleEditor extends Component {
@@ -163,27 +171,58 @@ export class VectorStyleEditor extends Component {
);
}
+ _renderLabelProperties() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
_renderPointProperties() {
let iconOrientation;
if (this.props.symbolDescriptor.options.symbolizeAs === SYMBOLIZE_AS_ICON) {
iconOrientation = (
-
-
-
-
+
);
}
@@ -207,8 +246,12 @@ export class VectorStyleEditor extends Component {
{iconOrientation}
+
{this._renderSymbolSize()}
+
+
+ {this._renderLabelProperties()}
);
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
index fdbb19a60d2e6..0e019994f74a1 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
@@ -46,6 +46,12 @@ export class DynamicColorProperty extends DynamicStyleProperty {
mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
}
+ syncLabelColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'text-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha);
+ }
+
isCustomColorRamp() {
return this._options.useCustomColorRamp;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
index 78409ef0d488f..d8a68701c1820 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
@@ -43,6 +43,10 @@ function getSymbolSizeIcons() {
}
export class DynamicSizeProperty extends DynamicStyleProperty {
+ supportsFeatureState() {
+ return this.getStyleName() !== VECTOR_STYLES.LABEL_SIZE;
+ }
+
syncHaloWidthWithMb(mbLayerId, mbMap) {
const haloWidth = this._getMbSize();
mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth);
@@ -89,6 +93,11 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth);
}
+ syncLabelSizeWithMb(mbLayerId, mbMap) {
+ const lineWidth = this._getMbSize();
+ mbMap.setLayoutProperty(mbLayerId, 'text-size', lineWidth);
+ }
+
_getMbSize() {
if (this._isSizeDynamicConfigComplete(this._options)) {
return this._getMbDataDrivenSize({
@@ -101,10 +110,11 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
}
_getMbDataDrivenSize({ targetName, minSize, maxSize }) {
+ const lookup = this.supportsFeatureState() ? 'feature-state' : 'get';
return [
'interpolate',
['linear'],
- ['coalesce', ['feature-state', targetName], 0],
+ ['coalesce', [lookup, targetName], 0],
0,
minSize,
1,
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
index 3b25746717088..9c55332d069b8 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
@@ -25,6 +25,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
return true;
}
+ isOrdinal() {
+ return true;
+ }
+
isComplete() {
return !!this._field;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js
new file mode 100644
index 0000000000000..b716030d2f263
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js
@@ -0,0 +1,39 @@
+/*
+ * 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';
+
+export class DynamicTextProperty extends DynamicStyleProperty {
+ syncTextFieldWithMb(mbLayerId, mbMap) {
+ if (this._field && this._field.isValid()) {
+ const targetName = getComputedFieldName(this._styleName, this._options.field.name);
+ mbMap.setLayoutProperty(mbLayerId, 'text-field', ['coalesce', ['get', targetName], '']);
+ } else {
+ mbMap.setLayoutProperty(mbLayerId, 'text-field', null);
+ }
+ }
+
+ isOrdinal() {
+ return false;
+ }
+
+ supportsFieldMeta() {
+ return false;
+ }
+
+ supportsFeatureState() {
+ return false;
+ }
+
+ isScaled() {
+ return false;
+ }
+
+ renderHeader() {
+ return null;
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
index a32b17af0be9e..658eb6a164556 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
@@ -30,8 +30,13 @@ export class StaticColorProperty extends StaticStyleProperty {
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);
+ syncCircleStrokeWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-opacity', alpha);
+ }
+
+ syncLabelColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'text-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha);
}
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
index d2682a07def62..1584dec998986 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
@@ -43,4 +43,8 @@ export class StaticSizeProperty extends StaticStyleProperty {
syncLineWidthWithMb(mbLayerId, mbMap) {
mbMap.setPaintProperty(mbLayerId, 'line-width', this._options.size);
}
+
+ syncLabelSizeWithMb(mbLayerId, mbMap) {
+ mbMap.setLayoutProperty(mbLayerId, 'text-size', this._options.size);
+ }
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_text_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_text_property.js
new file mode 100644
index 0000000000000..7a4a4672152c0
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_text_property.js
@@ -0,0 +1,21 @@
+/*
+ * 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 StaticTextProperty extends StaticStyleProperty {
+ isComplete() {
+ return this.getOptions().value.length > 0;
+ }
+
+ syncTextFieldWithMb(mbLayerId, mbMap) {
+ if (this.getOptions().value.length) {
+ mbMap.setLayoutProperty(mbLayerId, 'text-field', this.getOptions().value);
+ } else {
+ mbMap.setLayoutProperty(mbLayerId, 'text-field', null);
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
index 161c0ea69e86c..8e7cd8ed9831c 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
@@ -36,6 +36,8 @@ 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';
+import { StaticTextProperty } from './properties/static_text_property';
+import { DynamicTextProperty } from './properties/dynamic_text_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];
@@ -81,11 +83,21 @@ export class VectorStyle extends AbstractStyle {
this._descriptor.properties[VECTOR_STYLES.ICON_SIZE],
VECTOR_STYLES.ICON_SIZE
);
-
this._iconOrientationProperty = this._makeOrientationProperty(
this._descriptor.properties[VECTOR_STYLES.ICON_ORIENTATION],
VECTOR_STYLES.ICON_ORIENTATION
);
+ this._labelStyleProperty = this._makeLabelProperty(
+ this._descriptor.properties[VECTOR_STYLES.LABEL_TEXT]
+ );
+ this._labelSizeStyleProperty = this._makeSizeProperty(
+ this._descriptor.properties[VECTOR_STYLES.LABEL_SIZE],
+ VECTOR_STYLES.LABEL_SIZE
+ );
+ this._labelColorStyleProperty = this._makeColorProperty(
+ this._descriptor.properties[VECTOR_STYLES.LABEL_COLOR],
+ VECTOR_STYLES.LABEL_COLOR
+ );
}
_getAllStyleProperties() {
@@ -95,6 +107,9 @@ export class VectorStyle extends AbstractStyle {
this._lineWidthStyleProperty,
this._iconSizeStyleProperty,
this._iconOrientationProperty,
+ this._labelStyleProperty,
+ this._labelSizeStyleProperty,
+ this._labelColorStyleProperty,
];
}
@@ -115,16 +130,15 @@ export class VectorStyle extends AbstractStyle {
return dynamicStyleProp.isFieldMetaEnabled();
});
+ const styleProperties = {};
+ this._getAllStyleProperties().forEach(styleProperty => {
+ styleProperties[styleProperty.getStyleName()] = styleProperty;
+ });
+
return (
{
+ const styleName = styleProperty.getStyleName();
+ if ([VECTOR_STYLES.ICON_ORIENTATION, VECTOR_STYLES.LABEL_TEXT].includes(styleName)) {
+ return false;
+ }
+
if (isLinesOnly) {
- return LINE_STYLES.includes(styleProperty.getStyleName());
+ return LINE_STYLES.includes(styleName);
}
if (isPolygonsOnly) {
- return POLYGON_STYLES.includes(styleProperty.getStyleName());
+ return POLYGON_STYLES.includes(styleName);
}
return true;
@@ -433,6 +452,7 @@ export class VectorStyle extends AbstractStyle {
// To work around this limitation, some styling values must fall back to geojson property values.
let supportsFeatureState;
let isScaled;
+ // TODO move first check into DynamicSizeProperty.supportsFeatureState
if (
styleProperty.getStyleName() === VECTOR_STYLES.ICON_SIZE &&
this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_ICON
@@ -448,8 +468,10 @@ export class VectorStyle extends AbstractStyle {
return {
supportsFeatureState,
isScaled,
+ isOrdinal: styleProperty.isOrdinal(),
name: field.getName(),
meta: this._getFieldMeta(field.getName()),
+ formatter: this._getFieldFormatter(field.getName()),
computedName: getComputedFieldName(styleProperty.getStyleName(), field.getName()),
};
});
@@ -468,6 +490,20 @@ export class VectorStyle extends AbstractStyle {
}
}
+ _getOrdinalValue(value, isScaled, range) {
+ const valueAsFloat = parseFloat(value);
+
+ if (isScaled) {
+ return scaleValue(valueAsFloat, range);
+ }
+
+ if (isNaN(valueAsFloat)) {
+ return 0;
+ }
+
+ return valueAsFloat;
+ }
+
setFeatureStateAndStyleProps(featureCollection, mbMap, mbSourceId) {
if (!featureCollection) {
return;
@@ -492,20 +528,20 @@ export class VectorStyle extends AbstractStyle {
const {
supportsFeatureState,
isScaled,
+ isOrdinal,
name,
meta: range,
+ formatter,
computedName,
} = featureStateParams[j];
- const value = parseFloat(feature.properties[name]);
+
let styleValue;
- if (isScaled) {
- styleValue = scaleValue(value, range);
+ if (isOrdinal) {
+ styleValue = this._getOrdinalValue(feature.properties[name], isScaled, range);
+ } else if (formatter) {
+ styleValue = formatter(feature.properties[name]);
} else {
- if (isNaN(value)) {
- styleValue = 0;
- } else {
- styleValue = value;
- }
+ styleValue = feature.properties[name];
}
if (supportsFeatureState) {
@@ -543,6 +579,14 @@ export class VectorStyle extends AbstractStyle {
this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap);
}
+ setMBPropertiesForLabelText({ alpha, mbMap, textLayerId }) {
+ mbMap.setLayoutProperty(textLayerId, 'icon-allow-overlap', true);
+ mbMap.setLayoutProperty(textLayerId, 'text-allow-overlap', true);
+ this._labelStyleProperty.syncTextFieldWithMb(textLayerId, mbMap);
+ this._labelColorStyleProperty.syncLabelColorWithMb(textLayerId, mbMap, alpha);
+ this._labelSizeStyleProperty.syncLabelSizeWithMb(textLayerId, mbMap);
+ }
+
setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
const symbolId = this._descriptor.properties.symbol.options.symbolId;
mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
@@ -620,4 +664,17 @@ export class VectorStyle extends AbstractStyle {
throw new Error(`${descriptor} not implemented`);
}
}
+
+ _makeLabelProperty(descriptor) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticTextProperty({ value: '' }, VECTOR_STYLES.LABEL_TEXT);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticTextProperty(descriptor.options, VECTOR_STYLES.LABEL_TEXT);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ const field = this._makeField(descriptor.options.field);
+ return new DynamicTextProperty(descriptor.options, VECTOR_STYLES.LABEL_TEXT, field);
+ } else {
+ throw new Error(`${descriptor} not implemented`);
+ }
+ }
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
index 1242d7307dc48..aa0badd5583d5 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
@@ -96,6 +96,24 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
},
type: 'DYNAMIC',
},
+ labelText: {
+ options: {
+ value: '',
+ },
+ type: 'STATIC',
+ },
+ labelColor: {
+ options: {
+ color: '#000000',
+ },
+ type: 'STATIC',
+ },
+ labelSize: {
+ options: {
+ size: 14,
+ },
+ type: 'STATIC',
+ },
lineColor: {
options: {},
type: 'DYNAMIC',
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
index 3f2851fa092cd..4bae90c3165f2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
@@ -7,11 +7,14 @@
import { VectorStyle } from './vector_style';
import { SYMBOLIZE_AS_CIRCLE, DEFAULT_ICON_SIZE } from './vector_constants';
import { COLOR_GRADIENTS, DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../color_utils';
+import chrome from 'ui/chrome';
const DEFAULT_ICON = 'airfield';
export const MIN_SIZE = 1;
export const MAX_SIZE = 64;
+export const DEFAULT_MIN_SIZE = 4;
+export const DEFAULT_MAX_SIZE = 32;
export const DEFAULT_SIGMA = 3;
export const VECTOR_STYLES = {
@@ -21,6 +24,9 @@ export const VECTOR_STYLES = {
LINE_WIDTH: 'lineWidth',
ICON_SIZE: 'iconSize',
ICON_ORIENTATION: 'iconOrientation',
+ LABEL_TEXT: 'labelText',
+ LABEL_COLOR: 'labelColor',
+ LABEL_SIZE: 'labelSize',
};
export const LINE_STYLES = [VECTOR_STYLES.LINE_COLOR, VECTOR_STYLES.LINE_WIDTH];
@@ -49,6 +55,8 @@ export function getDefaultStaticProperties(mapColors = []) {
const nextFillColor = DEFAULT_FILL_COLORS[nextColorIndex];
const nextLineColor = DEFAULT_LINE_COLORS[nextColorIndex];
+ const isDarkMode = chrome.getUiSettingsClient().get('theme:darkMode', false);
+
return {
[VECTOR_STYLES.FILL_COLOR]: {
type: VectorStyle.STYLE_TYPE.STATIC,
@@ -80,6 +88,24 @@ export function getDefaultStaticProperties(mapColors = []) {
orientation: 0,
},
},
+ [VECTOR_STYLES.LABEL_TEXT]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ value: '',
+ },
+ },
+ [VECTOR_STYLES.LABEL_COLOR]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ color: isDarkMode ? '#FFFFFF' : '#000000',
+ },
+ },
+ [VECTOR_STYLES.LABEL_SIZE]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ size: 14,
+ },
+ },
};
}
@@ -122,8 +148,8 @@ export function getDefaultDynamicProperties() {
[VECTOR_STYLES.ICON_SIZE]: {
type: VectorStyle.STYLE_TYPE.DYNAMIC,
options: {
- minSize: 4,
- maxSize: 32,
+ minSize: DEFAULT_MIN_SIZE,
+ maxSize: DEFAULT_MAX_SIZE,
field: undefined,
fieldMetaOptions: {
isEnabled: true,
@@ -141,5 +167,34 @@ export function getDefaultDynamicProperties() {
},
},
},
+ [VECTOR_STYLES.LABEL_TEXT]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ field: undefined,
+ },
+ },
+ [VECTOR_STYLES.LABEL_COLOR]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ color: COLOR_GRADIENTS[0].value,
+ field: undefined,
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: DEFAULT_SIGMA,
+ },
+ },
+ },
+ [VECTOR_STYLES.LABEL_SIZE]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ minSize: DEFAULT_MIN_SIZE,
+ maxSize: DEFAULT_MAX_SIZE,
+ field: undefined,
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: DEFAULT_SIGMA,
+ },
+ },
+ },
};
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
index 30c47658bb327..6ebc1b3d95250 100644
--- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
@@ -191,24 +191,33 @@ export class VectorLayer extends AbstractLayer {
return this._source.getDisplayName();
}
+ _getJoinFields() {
+ const joinFields = [];
+ this.getValidJoins().forEach(join => {
+ const fields = join.getJoinFields();
+ joinFields.push(...fields);
+ });
+ return joinFields;
+ }
+
async getDateFields() {
return await this._source.getDateFields();
}
async getNumberFields() {
const numberFieldOptions = await this._source.getNumberFields();
- const joinFields = [];
- this.getValidJoins().forEach(join => {
- const fields = join.getJoinFields();
- joinFields.push(...fields);
- });
- return [...numberFieldOptions, ...joinFields];
+ return [...numberFieldOptions, ...this._getJoinFields()];
}
async getOrdinalFields() {
return [...(await this.getDateFields()), ...(await this.getNumberFields())];
}
+ async getFields() {
+ const sourceFields = await this._source.getFields();
+ return [...sourceFields, ...this._getJoinFields()];
+ }
+
getIndexPatternIds() {
const indexPatternIds = this._source.getIndexPatternIds();
this.getValidJoins().forEach(join => {
@@ -621,30 +630,40 @@ export class VectorLayer extends AbstractLayer {
const pointLayer = mbMap.getLayer(pointLayerId);
const symbolLayer = mbMap.getLayer(symbolLayerId);
- let mbLayerId;
+ // Point layers symbolized as circles require 2 mapbox layers because
+ // "circle" layers do not support "text" style properties
+ // Point layers symbolized as icons only contain a single mapbox layer.
+ let markerLayerId;
+ let textLayerId;
if (this._style.arePointsSymbolizedAsCircles()) {
- mbLayerId = pointLayerId;
+ markerLayerId = pointLayerId;
+ textLayerId = this._getMbTextLayerId();
if (symbolLayer) {
mbMap.setLayoutProperty(symbolLayerId, 'visibility', 'none');
}
this._setMbCircleProperties(mbMap);
} else {
- mbLayerId = symbolLayerId;
+ markerLayerId = symbolLayerId;
+ textLayerId = symbolLayerId;
if (pointLayer) {
mbMap.setLayoutProperty(pointLayerId, 'visibility', 'none');
+ mbMap.setLayoutProperty(this._getMbTextLayerId(), 'visibility', 'none');
}
this._setMbSymbolProperties(mbMap);
}
- this.syncVisibilityWithMb(mbMap, mbLayerId);
- mbMap.setLayerZoomRange(mbLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
+ this.syncVisibilityWithMb(mbMap, markerLayerId);
+ mbMap.setLayerZoomRange(markerLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
+ if (markerLayerId !== textLayerId) {
+ this.syncVisibilityWithMb(mbMap, textLayerId);
+ mbMap.setLayerZoomRange(textLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
+ }
}
_setMbCircleProperties(mbMap) {
const sourceId = this.getId();
const pointLayerId = this._getMbPointLayerId();
const pointLayer = mbMap.getLayer(pointLayerId);
-
if (!pointLayer) {
mbMap.addLayer({
id: pointLayerId,
@@ -654,15 +673,32 @@ export class VectorLayer extends AbstractLayer {
});
}
+ const textLayerId = this._getMbTextLayerId();
+ const textLayer = mbMap.getLayer(textLayerId);
+ if (!textLayer) {
+ mbMap.addLayer({
+ id: textLayerId,
+ type: 'symbol',
+ source: sourceId,
+ });
+ }
+
const filterExpr = getPointFilterExpression(this._hasJoins());
if (filterExpr !== mbMap.getFilter(pointLayerId)) {
mbMap.setFilter(pointLayerId, filterExpr);
+ mbMap.setFilter(textLayerId, filterExpr);
}
this._style.setMBPaintPropertiesForPoints({
alpha: this.getAlpha(),
mbMap,
- pointLayerId: pointLayerId,
+ pointLayerId,
+ });
+
+ this._style.setMBPropertiesForLabelText({
+ alpha: this.getAlpha(),
+ mbMap,
+ textLayerId,
});
}
@@ -687,7 +723,13 @@ export class VectorLayer extends AbstractLayer {
this._style.setMBSymbolPropertiesForPoints({
alpha: this.getAlpha(),
mbMap,
- symbolLayerId: symbolLayerId,
+ symbolLayerId,
+ });
+
+ this._style.setMBPropertiesForLabelText({
+ alpha: this.getAlpha(),
+ mbMap,
+ textLayerId: symbolLayerId,
});
}
@@ -759,6 +801,10 @@ export class VectorLayer extends AbstractLayer {
return this.makeMbLayerId('circle');
}
+ _getMbTextLayerId() {
+ return this.makeMbLayerId('text');
+ }
+
_getMbSymbolLayerId() {
return this.makeMbLayerId('symbol');
}
@@ -774,6 +820,7 @@ export class VectorLayer extends AbstractLayer {
getMbLayerIds() {
return [
this._getMbPointLayerId(),
+ this._getMbTextLayerId(),
this._getMbSymbolLayerId(),
this._getMbLineLayerId(),
this._getMbPolygonLayerId(),
@@ -781,12 +828,7 @@ export class VectorLayer extends AbstractLayer {
}
ownsMbLayerId(mbLayerId) {
- return (
- this._getMbPointLayerId() === mbLayerId ||
- this._getMbLineLayerId() === mbLayerId ||
- this._getMbPolygonLayerId() === mbLayerId ||
- this._getMbSymbolLayerId() === mbLayerId
- );
+ return this.getMbLayerIds().includes(mbLayerId);
}
ownsMbSourceId(mbSourceId) {
diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js
index cbe7c98cd881d..89a6c6ea82e53 100644
--- a/x-pack/test/functional/apps/maps/joins.js
+++ b/x-pack/test/functional/apps/maps/joins.js
@@ -18,6 +18,9 @@ const EXPECTED_JOIN_VALUES = {
};
const VECTOR_SOURCE_ID = 'n1t6f';
+const CIRCLE_STYLE_LAYER_INDEX = 0;
+const FILL_STYLE_LAYER_INDEX = 2;
+const LINE_STYLE_LAYER_INDEX = 3;
export default function({ getPageObjects, getService }) {
const PageObjects = getPageObjects(['maps']);
@@ -82,19 +85,21 @@ export default function({ getPageObjects, getService }) {
const layersForVectorSource = mapboxStyle.layers.filter(mbLayer => {
return mbLayer.id.startsWith(VECTOR_SOURCE_ID);
});
+
// Color is dynamically obtained from eui source lib
- const dynamicColor = layersForVectorSource[0].paint['circle-stroke-color'];
+ const dynamicColor =
+ layersForVectorSource[CIRCLE_STYLE_LAYER_INDEX].paint['circle-stroke-color'];
//circle layer for points
- expect(layersForVectorSource[0]).to.eql(
+ expect(layersForVectorSource[CIRCLE_STYLE_LAYER_INDEX]).to.eql(
_.set(MAPBOX_STYLES.POINT_LAYER, 'paint.circle-stroke-color', dynamicColor)
);
//fill layer
- expect(layersForVectorSource[1]).to.eql(MAPBOX_STYLES.FILL_LAYER);
+ expect(layersForVectorSource[FILL_STYLE_LAYER_INDEX]).to.eql(MAPBOX_STYLES.FILL_LAYER);
//line layer for borders
- expect(layersForVectorSource[2]).to.eql(
+ expect(layersForVectorSource[LINE_STYLE_LAYER_INDEX]).to.eql(
_.set(MAPBOX_STYLES.LINE_LAYER, 'paint.line-color', dynamicColor)
);
});