Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Maps] Enable borders for icon symbols #43066

Merged
merged 7 commits into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/maps/vector-style-properties.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ 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.

*Symbol orientation*:: The symbol orientation rotating the icon clockwise.

*Symbol size*:: The radius of the symbol size, in pixels.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,35 @@ export class SymbolIcon extends Component {
imgDataUrl: undefined,
prevSymbolId: undefined,
prevFill: undefined,
prevStroke: undefined,
prevStrokeWidth: undefined,
}

componentDidMount() {
this._isMounted = true;
this._loadSymbol(this.props.symbolId, this.props.fill);
this._loadSymbol(this.props.symbolId, this.props.fill, this.props.stroke, this.props.strokeWidth);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update SymbolIcon.propTypes definition at end of file to include stroke and strokeWidth

}

componentDidUpdate() {
this._loadSymbol(this.props.symbolId, this.props.fill);
this._loadSymbol(this.props.symbolId, this.props.fill, this.props.stroke, this.props.strokeWidth);
}

componentWillUnmount() {
this._isMounted = false;
}

async _loadSymbol(nextSymbolId, nextFill) {
async _loadSymbol(nextSymbolId, nextFill, nextStroke, nextStrokeWidth) {
if (nextSymbolId === this.state.prevSymbolId
&& nextFill === this.state.prevFill) {
&& nextFill === this.state.prevFill
&& nextStroke === this.state.prevStroke
&& nextStrokeWidth === this.state.prevStrokeWidth) {
return;
}

let imgDataUrl;
try {
const svg = getMakiSymbolSvg(nextSymbolId);
const styledSvg = await styleSvg(svg, nextFill);
const styledSvg = await styleSvg(svg, nextFill, nextStroke, nextStrokeWidth);
imgDataUrl = buildSrcUrl(styledSvg);
} catch (error) {
// ignore failures - component will just not display an icon
Expand All @@ -49,7 +53,9 @@ export class SymbolIcon extends Component {
this.setState({
imgDataUrl,
prevSymbolId: nextSymbolId,
prevFill: nextFill
prevFill: nextFill,
prevStroke: nextStroke,
prevStrokeWidth: nextStrokeWidth
});
}
}
Expand All @@ -68,4 +74,6 @@ export class SymbolIcon extends Component {
SymbolIcon.propTypes = {
symbolId: PropTypes.string.isRequired,
fill: PropTypes.string.isRequired,
stroke: PropTypes.string.isRequired,
strokeWidth: PropTypes.string.isRequired
};
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export class VectorIcon extends Component {
<SymbolIcon
symbolId={this.props.symbolId}
fill={style.fill}
stroke={style.stroke}
strokeWidth={style.strokeWidth}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { VectorStyleSymbolEditor } from './vector_style_symbol_editor';
import { OrientationEditor } from './orientation/orientation_editor';
import { getDefaultDynamicProperties, getDefaultStaticProperties } from '../../vector_style_defaults';
import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types';
import { SYMBOLIZE_AS_CIRCLE } from '../../vector_constants';
import { SYMBOLIZE_AS_ICON } from '../../vector_constants';
import { i18n } from '@kbn/i18n';
import { SYMBOL_OPTIONS } from '../../symbol_utils';

Expand Down Expand Up @@ -140,23 +140,8 @@ export class VectorStyleEditor extends Component {
}

_renderPointProperties() {
let lineColor;
let lineWidth;
let iconOrientation;
if (this.props.styleProperties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE) {
lineColor = (
<Fragment>
{this._renderLineColor()}
<EuiSpacer size="m" />
</Fragment>
);
lineWidth = (
<Fragment>
{this._renderLineWidth()}
<EuiSpacer size="m" />
</Fragment>
);
} else {
if (this.props.styleProperties.symbol.options.symbolizeAs === SYMBOLIZE_AS_ICON) {
iconOrientation = (
<Fragment>
<OrientationEditor
Expand Down Expand Up @@ -185,9 +170,15 @@ export class VectorStyleEditor extends Component {
{this._renderFillColor()}
<EuiSpacer size="m" />

{lineColor}
<Fragment>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fragment wrapper is not needed here

{this._renderLineColor()}
<EuiSpacer size="m" />
</Fragment>

{lineWidth}
<Fragment>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fragment wrapper is not needed here

{this._renderLineWidth()}
<EuiSpacer size="m" />
</Fragment>

{iconOrientation}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ export function VectorStyleSymbolEditor({ styleOptions, handlePropertyChange, sy
<SymbolIcon
symbolId={value}
fill={isDarkMode ? 'rgb(223, 229, 239)' : 'rgb(52, 55, 65)'}
stroke={isDarkMode ? 'rgb(255, 255, 255)' : 'rgb(0, 0, 0)'}
strokeWidth={'1px'}
/>
</EuiFlexItem>
<EuiFlexItem>
Expand Down
12 changes: 10 additions & 2 deletions x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,19 @@ export function buildSrcUrl(svgString) {
return domUrl.createObjectURL(svg);
}

export async function styleSvg(svgString, fill) {
export async function styleSvg(svgString, fill, stroke, strokeWidth) {
const svgXml = await parseXmlString(svgString);
let style = '';
if (fill) {
svgXml.svg.$.style = `fill: ${fill};`;
style += `fill:${fill};`;
}
if (stroke) {
style += `stroke:${stroke};`;
}
if (strokeWidth) {
style += `stroke-width:${strokeWidth};`;
}
if (style) svgXml.svg.$.style = style;
const builder = new xml2js.Builder();
return builder.buildObject(svgXml);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,30 @@ describe('getMakiSymbolSvg', () => {
});

describe('styleSvg', () => {
it('Should not add style property when fill not provided', async () => {
it('Should not add style property when style not provided', async () => {
const unstyledSvgString = '<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString);
expect(styledSvg.split('\n')[1]).toBe('<svg version=\"1.1\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11 11\">');
});

it('Should add style property to svg element', async () => {
it('Should add fill style property to svg element', async () => {
const unstyledSvgString = '<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'red');
// eslint-disable-next-line max-len
expect(styledSvg.split('\n')[1]).toBe('<svg version=\"1.1\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11 11\" style=\"fill: red;\">');
expect(styledSvg.split('\n')[1]).toBe('<svg version=\"1.1\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11 11\" style=\"fill:red;\">');
});

it('Should add stroke style property to svg element', async () => {
const unstyledSvgString = '<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'red', 'white');
// eslint-disable-next-line max-len
expect(styledSvg.split('\n')[1]).toBe('<svg version=\"1.1\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11 11\" style=\"fill:red;stroke:white;\">');
});

it('Should add stroke-width style property to svg element', async () => {
const unstyledSvgString = '<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'red', 'white', '2px');
// eslint-disable-next-line max-len
expect(styledSvg.split('\n')[1]).toBe('<svg version=\"1.1\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11 11\" style=\"fill:red;stroke:white;stroke-width:2px;\">');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,12 @@ export class VectorStyle extends AbstractStyle {
const symbolId = this._descriptor.properties.symbol.options.symbolId;
mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
const color = this._getMBColor(this._descriptor.properties.fillColor);
const haloColor = this._getMBColor(this._descriptor.properties.lineColor);
const haloWidth = this._getMbSize(this._descriptor.properties.lineWidth);
// icon-color is only supported on SDF icons.
mbMap.setPaintProperty(symbolLayerId, 'icon-color', color);
mbMap.setPaintProperty(symbolLayerId, 'icon-halo-color', haloColor);
mbMap.setPaintProperty(symbolLayerId, 'icon-halo-width', haloWidth);
mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);

// circle sizing is by radius
Expand Down