* [Maps] add text halo color and width style properties * fix jest test * update for new editor UI * add removed styling * get halo size from label size * fix label border size with dynamic label size * clean up * fix jest test * fix jest test Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
1ccd5705b1
commit
a90e9fd204
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<EuiFormRow
|
||||
label={getVectorStyleLabel(VECTOR_STYLES.LABEL_BORDER_SIZE)}
|
||||
display="columnCompressed"
|
||||
>
|
||||
<EuiSelect
|
||||
options={options}
|
||||
value={styleProperty.getOptions().size}
|
||||
onChange={onChange}
|
||||
aria-label={i18n.translate('xpack.maps.styles.labelBorderSizeSelect.ariaLabel', {
|
||||
defaultMessage: 'Select label border size',
|
||||
})}
|
||||
compressed
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
|
@ -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 {
|
|||
}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<VectorStyleColorEditor
|
||||
swatches={DEFAULT_LINE_COLORS}
|
||||
onStaticStyleChange={this._onStaticStyleChange}
|
||||
onDynamicStyleChange={this._onDynamicStyleChange}
|
||||
styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_BORDER_COLOR]}
|
||||
fields={this._getOrdinalFields()}
|
||||
defaultStaticStyleOptions={
|
||||
this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_BORDER_COLOR].options
|
||||
}
|
||||
defaultDynamicStyleOptions={
|
||||
this.state.defaultDynamicProperties[VECTOR_STYLES.LABEL_BORDER_COLOR].options
|
||||
}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<VectorStyleLabelBorderSizeEditor
|
||||
handlePropertyChange={this.props.handlePropertyChange}
|
||||
styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_BORDER_SIZE]}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 <div>mockVectorStyleEditor</div>;
|
||||
},
|
||||
}));
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }) {
|
||||
|
|
|
@ -102,6 +102,17 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
|
|||
},
|
||||
type: 'STATIC',
|
||||
},
|
||||
labelBorderColor: {
|
||||
options: {
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
type: 'STATIC',
|
||||
},
|
||||
labelBorderSize: {
|
||||
options: {
|
||||
size: 'SMALL',
|
||||
},
|
||||
},
|
||||
labelColor: {
|
||||
options: {
|
||||
color: '#000000',
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue