diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
index 325fc28f92051b..16cfd34c95ab36 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
@@ -42,6 +42,14 @@ export function getVectorStyleLabel(styleName) {
return i18n.translate('xpack.maps.styles.vector.labelSizeLabel', {
defaultMessage: 'Label size',
});
+ case VECTOR_STYLES.LABEL_BORDER_COLOR:
+ return i18n.translate('xpack.maps.styles.vector.labelBorderColorLabel', {
+ defaultMessage: 'Label border color',
+ });
+ case VECTOR_STYLES.LABEL_BORDER_SIZE:
+ return i18n.translate('xpack.maps.styles.vector.labelBorderWidthLabel', {
+ defaultMessage: 'Label border width',
+ });
default:
return styleName;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js
new file mode 100644
index 00000000000000..7d06e8b530011b
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js
@@ -0,0 +1,65 @@
+/*
+ * 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 { EuiFormRow, EuiSelect } from '@elastic/eui';
+import { LABEL_BORDER_SIZES, VECTOR_STYLES } from '../../vector_style_defaults';
+import { getVectorStyleLabel } from '../get_vector_style_label';
+import { i18n } from '@kbn/i18n';
+
+const options = [
+ {
+ value: LABEL_BORDER_SIZES.NONE,
+ text: i18n.translate('xpack.maps.styles.labelBorderSize.noneLabel', {
+ defaultMessage: 'None',
+ }),
+ },
+ {
+ value: LABEL_BORDER_SIZES.SMALL,
+ text: i18n.translate('xpack.maps.styles.labelBorderSize.smallLabel', {
+ defaultMessage: 'Small',
+ }),
+ },
+ {
+ value: LABEL_BORDER_SIZES.MEDIUM,
+ text: i18n.translate('xpack.maps.styles.labelBorderSize.mediumLabel', {
+ defaultMessage: 'Medium',
+ }),
+ },
+ {
+ value: LABEL_BORDER_SIZES.LARGE,
+ text: i18n.translate('xpack.maps.styles.labelBorderSize.largeLabel', {
+ defaultMessage: 'Large',
+ }),
+ },
+];
+
+export function VectorStyleLabelBorderSizeEditor({ handlePropertyChange, styleProperty }) {
+ function onChange(e) {
+ const styleDescriptor = {
+ options: { size: e.target.value },
+ };
+ handlePropertyChange(styleProperty.getStyleName(), styleDescriptor);
+ }
+
+ 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 dffe513644db84..bd22b4b9cc5cee 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
@@ -12,6 +12,7 @@ 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 { VectorStyleLabelBorderSizeEditor } from './label/vector_style_label_border_size_editor';
import { VectorStyle } from '../vector_style';
import { OrientationEditor } from './orientation/orientation_editor';
import {
@@ -248,6 +249,27 @@ export class VectorStyleEditor extends Component {
}
/>
+
+
+
+
+
+
);
}
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 57e4d09f3abecd..804a0f8975d3eb 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
@@ -55,6 +55,11 @@ export class DynamicColorProperty extends DynamicStyleProperty {
mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha);
}
+ syncLabelBorderColorWithMb(mbLayerId, mbMap) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'text-halo-color', color);
+ }
+
isCustomColorRamp() {
return this._options.useCustomColorRamp;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js
index 0affeefde13135..21c24e837b412a 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js
@@ -4,7 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-// eslint-disable-next-line no-unused-vars
+jest.mock('../components/vector_style_editor', () => ({
+ VectorStyleEditor: () => {
+ return
mockVectorStyleEditor
;
+ },
+}));
+
import React from 'react';
import { shallow } from 'enzyme';
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 f2e56722268148..5a4da1a80c9187 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
@@ -5,7 +5,7 @@
*/
import { DynamicStyleProperty } from './dynamic_style_property';
-import { getComputedFieldName } from '../style_util';
+
import {
HALF_LARGE_MAKI_ICON_SIZE,
LARGE_MAKI_ICON_SIZE,
@@ -63,7 +63,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
}
syncHaloWidthWithMb(mbLayerId, mbMap) {
- const haloWidth = this._getMbSize();
+ const haloWidth = this.getMbSizeExpression();
mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth);
}
@@ -76,7 +76,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
const halfIconPixels = iconPixels / 2;
- const targetName = getComputedFieldName(VECTOR_STYLES.ICON_SIZE, this._options.field.name);
+ const targetName = this.getComputedFieldName();
// Using property state instead of feature-state because layout properties do not support feature-state
mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
'interpolate',
@@ -94,29 +94,29 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
}
syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
- const lineWidth = this._getMbSize();
+ const lineWidth = this.getMbSizeExpression();
mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
}
syncCircleRadiusWithMb(mbLayerId, mbMap) {
- const circleRadius = this._getMbSize();
+ const circleRadius = this.getMbSizeExpression();
mbMap.setPaintProperty(mbLayerId, 'circle-radius', circleRadius);
}
syncLineWidthWithMb(mbLayerId, mbMap) {
- const lineWidth = this._getMbSize();
+ const lineWidth = this.getMbSizeExpression();
mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth);
}
syncLabelSizeWithMb(mbLayerId, mbMap) {
- const lineWidth = this._getMbSize();
+ const lineWidth = this.getMbSizeExpression();
mbMap.setLayoutProperty(mbLayerId, 'text-size', lineWidth);
}
- _getMbSize() {
+ getMbSizeExpression() {
if (this._isSizeDynamicConfigComplete(this._options)) {
return this._getMbDataDrivenSize({
- targetName: getComputedFieldName(this._styleName, this._options.field.name),
+ targetName: this.getComputedFieldName(),
minSize: this._options.minSize,
maxSize: this._options.maxSize,
});
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 cb5858fa47b3ef..97ab7cb78015bc 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
@@ -8,7 +8,7 @@ import _ from 'lodash';
import { AbstractStyleProperty } from './style_property';
import { DEFAULT_SIGMA } from '../vector_style_defaults';
import { STYLE_TYPE } from '../../../../../common/constants';
-import { scaleValue } from '../style_util';
+import { scaleValue, getComputedFieldName } from '../style_util';
import React from 'react';
import { OrdinalLegend } from './components/ordinal_legend';
import { CategoricalLegend } from './components/categorical_legend';
@@ -31,6 +31,13 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
return this._field;
}
+ getComputedFieldName() {
+ if (!this.isComplete()) {
+ return null;
+ }
+ return getComputedFieldName(this._styleName, this.getField().getName());
+ }
+
isDynamic() {
return true;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js
new file mode 100644
index 00000000000000..e08c2875c310eb
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js
@@ -0,0 +1,50 @@
+/*
+ * 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 _ from 'lodash';
+import { AbstractStyleProperty } from './style_property';
+import { DEFAULT_LABEL_SIZE, LABEL_BORDER_SIZES } from '../vector_style_defaults';
+
+const SMALL_SIZE = 1 / 16;
+const MEDIUM_SIZE = 1 / 8;
+const LARGE_SIZE = 1 / 5; // halo of 1/4 is just a square. Use smaller ratio to preserve contour on letters
+
+function getWidthRatio(size) {
+ switch (size) {
+ case LABEL_BORDER_SIZES.LARGE:
+ return LARGE_SIZE;
+ case LABEL_BORDER_SIZES.MEDIUM:
+ return MEDIUM_SIZE;
+ default:
+ return SMALL_SIZE;
+ }
+}
+
+export class LabelBorderSizeProperty extends AbstractStyleProperty {
+ constructor(options, styleName, labelSizeProperty) {
+ super(options, styleName);
+ this._labelSizeProperty = labelSizeProperty;
+ }
+
+ syncLabelBorderSizeWithMb(mbLayerId, mbMap) {
+ const widthRatio = getWidthRatio(this.getOptions().size);
+
+ if (this.getOptions().size === LABEL_BORDER_SIZES.NONE) {
+ mbMap.setPaintProperty(mbLayerId, 'text-halo-width', 0);
+ } else if (this._labelSizeProperty.isDynamic() && this._labelSizeProperty.isComplete()) {
+ const labelSizeExpression = this._labelSizeProperty.getMbSizeExpression();
+ mbMap.setPaintProperty(mbLayerId, 'text-halo-width', [
+ 'max',
+ ['*', labelSizeExpression, widthRatio],
+ 1,
+ ]);
+ } else {
+ const labelSize = _.get(this._labelSizeProperty.getOptions(), 'size', DEFAULT_LABEL_SIZE);
+ const labelBorderSize = Math.max(labelSize * widthRatio, 1);
+ mbMap.setPaintProperty(mbLayerId, 'text-halo-width', labelBorderSize);
+ }
+ }
+}
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 658eb6a164556f..ebe2a322711fc3 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
@@ -39,4 +39,8 @@ export class StaticColorProperty extends StaticStyleProperty {
mbMap.setPaintProperty(mbLayerId, 'text-color', this._options.color);
mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha);
}
+
+ syncLabelBorderColorWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'text-halo-color', this._options.color);
+ }
}
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 d1efcbb72d1a7e..30d1c5726ba481 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
@@ -38,6 +38,7 @@ import { StaticOrientationProperty } from './properties/static_orientation_prope
import { DynamicOrientationProperty } from './properties/dynamic_orientation_property';
import { StaticTextProperty } from './properties/static_text_property';
import { DynamicTextProperty } from './properties/dynamic_text_property';
+import { LabelBorderSizeProperty } from './properties/label_border_size_property';
import { extractColorFromStyleProperty } from './components/legend/extract_color_from_style_property';
const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
@@ -100,6 +101,15 @@ export class VectorStyle extends AbstractStyle {
this._descriptor.properties[VECTOR_STYLES.LABEL_COLOR],
VECTOR_STYLES.LABEL_COLOR
);
+ this._labelBorderColorStyleProperty = this._makeColorProperty(
+ this._descriptor.properties[VECTOR_STYLES.LABEL_BORDER_COLOR],
+ VECTOR_STYLES.LABEL_BORDER_COLOR
+ );
+ this._labelBorderSizeStyleProperty = new LabelBorderSizeProperty(
+ this._descriptor.properties[VECTOR_STYLES.LABEL_BORDER_SIZE].options,
+ VECTOR_STYLES.LABEL_BORDER_SIZE,
+ this._labelSizeStyleProperty
+ );
}
_getAllStyleProperties() {
@@ -112,6 +122,8 @@ export class VectorStyle extends AbstractStyle {
this._labelStyleProperty,
this._labelSizeStyleProperty,
this._labelColorStyleProperty,
+ this._labelBorderColorStyleProperty,
+ this._labelBorderSizeStyleProperty,
];
}
@@ -537,6 +549,8 @@ export class VectorStyle extends AbstractStyle {
this._labelStyleProperty.syncTextFieldWithMb(textLayerId, mbMap);
this._labelColorStyleProperty.syncLabelColorWithMb(textLayerId, mbMap, alpha);
this._labelSizeStyleProperty.syncLabelSizeWithMb(textLayerId, mbMap);
+ this._labelBorderSizeStyleProperty.syncLabelBorderSizeWithMb(textLayerId, mbMap);
+ this._labelBorderColorStyleProperty.syncLabelBorderColorWithMb(textLayerId, mbMap);
}
setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
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 3d2911720c3120..c250d83720580c 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
@@ -102,6 +102,17 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
},
type: 'STATIC',
},
+ labelBorderColor: {
+ options: {
+ color: '#FFFFFF',
+ },
+ type: 'STATIC',
+ },
+ labelBorderSize: {
+ options: {
+ size: 'SMALL',
+ },
+ },
labelColor: {
options: {
color: '#000000',
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 4bae90c3165f20..3631613e7907cd 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
@@ -16,6 +16,14 @@ export const MAX_SIZE = 64;
export const DEFAULT_MIN_SIZE = 4;
export const DEFAULT_MAX_SIZE = 32;
export const DEFAULT_SIGMA = 3;
+export const DEFAULT_LABEL_SIZE = 14;
+
+export const LABEL_BORDER_SIZES = {
+ NONE: 'NONE',
+ SMALL: 'SMALL',
+ MEDIUM: 'MEDIUM',
+ LARGE: 'LARGE',
+};
export const VECTOR_STYLES = {
SYMBOL: 'symbol',
@@ -27,6 +35,8 @@ export const VECTOR_STYLES = {
LABEL_TEXT: 'labelText',
LABEL_COLOR: 'labelColor',
LABEL_SIZE: 'labelSize',
+ LABEL_BORDER_COLOR: 'labelBorderColor',
+ LABEL_BORDER_SIZE: 'labelBorderSize',
};
export const LINE_STYLES = [VECTOR_STYLES.LINE_COLOR, VECTOR_STYLES.LINE_WIDTH];
@@ -45,6 +55,11 @@ export function getDefaultProperties(mapColors = []) {
symbolId: DEFAULT_ICON,
},
},
+ [VECTOR_STYLES.LABEL_BORDER_SIZE]: {
+ options: {
+ size: LABEL_BORDER_SIZES.SMALL,
+ },
+ },
};
}
@@ -103,7 +118,13 @@ export function getDefaultStaticProperties(mapColors = []) {
[VECTOR_STYLES.LABEL_SIZE]: {
type: VectorStyle.STYLE_TYPE.STATIC,
options: {
- size: 14,
+ size: DEFAULT_LABEL_SIZE,
+ },
+ },
+ [VECTOR_STYLES.LABEL_BORDER_COLOR]: {
+ type: VectorStyle.STYLE_TYPE.STATIC,
+ options: {
+ color: isDarkMode ? '#000000' : '#FFFFFF',
},
},
};
@@ -158,7 +179,7 @@ export function getDefaultDynamicProperties() {
},
},
[VECTOR_STYLES.ICON_ORIENTATION]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: VectorStyle.STYLE_TYPE.DYNAMIC,
options: {
field: undefined,
fieldMetaOptions: {
@@ -168,13 +189,13 @@ export function getDefaultDynamicProperties() {
},
},
[VECTOR_STYLES.LABEL_TEXT]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: VectorStyle.STYLE_TYPE.DYNAMIC,
options: {
field: undefined,
},
},
[VECTOR_STYLES.LABEL_COLOR]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: VectorStyle.STYLE_TYPE.DYNAMIC,
options: {
color: COLOR_GRADIENTS[0].value,
field: undefined,
@@ -185,7 +206,7 @@ export function getDefaultDynamicProperties() {
},
},
[VECTOR_STYLES.LABEL_SIZE]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: VectorStyle.STYLE_TYPE.DYNAMIC,
options: {
minSize: DEFAULT_MIN_SIZE,
maxSize: DEFAULT_MAX_SIZE,
@@ -196,5 +217,16 @@ export function getDefaultDynamicProperties() {
},
},
},
+ [VECTOR_STYLES.LABEL_BORDER_COLOR]: {
+ type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ options: {
+ color: COLOR_GRADIENTS[0].value,
+ field: undefined,
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: DEFAULT_SIGMA,
+ },
+ },
+ },
};
}