Skip to content

Commit

Permalink
[Maps] add text halo color and width style properties (#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 b65710d commit e9e44ec
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 16 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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>
);
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
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);
}
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit e9e44ec

Please sign in to comment.