Skip to content

Commit

Permalink
[Maps] add text halo color and width style properties (elastic#53827)
Browse files Browse the repository at this point in the history
* [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>
  • Loading branch information
nreese and elasticmachine committed Jan 13, 2020
1 parent 9aa8e5e commit 1953411
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 16 deletions.
Expand Up @@ -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;
}
Expand Down
@@ -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>
);
}
Expand Up @@ -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 {
Expand Down Expand Up @@ -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>
);
}
Expand Down
Expand Up @@ -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;
}
Expand Down
Expand Up @@ -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';

Expand Down
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

Expand All @@ -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',
Expand All @@ -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,
});
Expand Down
Expand Up @@ -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';
Expand All @@ -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;
}
Expand Down
@@ -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);
}
}
}
Expand Up @@ -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);
}
}
Expand Up @@ -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];
Expand Down Expand Up @@ -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() {
Expand All @@ -112,6 +122,8 @@ export class VectorStyle extends AbstractStyle {
this._labelStyleProperty,
this._labelSizeStyleProperty,
this._labelColorStyleProperty,
this._labelBorderColorStyleProperty,
this._labelBorderSizeStyleProperty,
];
}

Expand Down Expand Up @@ -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 }) {
Expand Down
Expand Up @@ -102,6 +102,17 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
},
type: 'STATIC',
},
labelBorderColor: {
options: {
color: '#FFFFFF',
},
type: 'STATIC',
},
labelBorderSize: {
options: {
size: 'SMALL',
},
},
labelColor: {
options: {
color: '#000000',
Expand Down

0 comments on commit 1953411

Please sign in to comment.