Skip to content

Commit

Permalink
TextLayer: support background color (#3903)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xintong Xia authored and georgios-uber committed Dec 13, 2019
1 parent b3afeac commit 742cff9
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 11 deletions.
7 changes: 7 additions & 0 deletions docs/layers/text-layer.md
Expand Up @@ -113,6 +113,13 @@ The maximum size in pixels.

If on, the text always faces camera. Otherwise the text faces up (z).

##### `backgroundColor` (Array, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

- Default `null`

The color to use for text background, in `[r, g, b]`. Each component is in the `[0, 255]` range.
The alpha of the background matches the opacity of each object, controlled by the props `getColor` and `opacity`.

##### `fontFamily` (String, optional)

* Default: `'Monaco, monospace'`
Expand Down
5 changes: 4 additions & 1 deletion modules/core/src/lifecycle/prop-types.js
Expand Up @@ -18,7 +18,10 @@ const TYPE_DEFINITIONS = {
},
color: {
validate(value, propType) {
return isArray(value) && (value.length === 3 || value.length === 4);
return (
(propType.optional && !value) ||
(isArray(value) && (value.length === 3 || value.length === 4))
);
},
equal(value1, value2, propType) {
return arrayEqual(value1, value2);
Expand Down
Expand Up @@ -27,6 +27,8 @@ uniform sampler2D iconsTexture;
uniform float buffer;
uniform bool sdf;
uniform float alphaCutoff;
uniform bool shouldDrawBackground;
uniform vec3 backgroundColor;
varying vec4 vColor;
varying vec2 vTextureCoords;
Expand All @@ -36,23 +38,35 @@ varying vec2 uv;
void main(void) {
geometry.uv = uv;
vec4 texColor = texture2D(iconsTexture, vTextureCoords);
float alpha = texColor.a;
float alpha = texture2D(iconsTexture, vTextureCoords).a;
// if enable sdf (signed distance fields)
if (sdf) {
float distance = texture2D(iconsTexture, vTextureCoords).a;
alpha = smoothstep(buffer - vGamma, buffer + vGamma, distance);
alpha = smoothstep(buffer - vGamma, buffer + vGamma, alpha);
}
// Take the global opacity and the alpha from vColor into account for the alpha component
float a = alpha * vColor.a;
if (a < alphaCutoff) {
discard;
// We are now in the background, let's decide what to draw
if (shouldDrawBackground && !picking_uActive) {
// draw background color and return if not picking
gl_FragColor = vec4(backgroundColor, vColor.a);
return;
} else if (!picking_uActive) {
// no background and no picking
discard;
}
// else (picking):
// allow picking to work and pick the background (fall-through to DECKGL_FILTER_COLOR)
}
gl_FragColor = vec4(vColor.rgb, a);
if (shouldDrawBackground) {
gl_FragColor = vec4(mix(backgroundColor, vColor.rgb, alpha), vColor.a);
} else {
gl_FragColor = vec4(vColor.rgb, a);
}
DECKGL_FILTER_COLOR(gl_FragColor, geometry);
}
Expand Down
17 changes: 15 additions & 2 deletions modules/layers/src/text-layer/multi-icon-layer/multi-icon-layer.js
Expand Up @@ -30,6 +30,7 @@ const DEFAULT_GAMMA = 0.2;
const DEFAULT_BUFFER = 192.0 / 256;

const defaultProps = {
backgroundColor: {type: 'color', value: null, optional: true},
// each paragraph can have one or multiple row(s)
// each row can have one or multiple character(s)
getRowSize: {type: 'accessor', value: x => x.rowSize || [0, 0]},
Expand Down Expand Up @@ -80,25 +81,37 @@ export default class MultiIconLayer extends IconLayer {

updateState(updateParams) {
super.updateState(updateParams);
const {changeFlags} = updateParams;
const {changeFlags, oldProps, props} = updateParams;

if (
changeFlags.updateTriggersChanged &&
(changeFlags.updateTriggersChanged.getAnchorX || changeFlags.updateTriggersChanged.getAnchorY)
) {
this.getAttributeManager().invalidate('instanceOffsets');
}

if (props.backgroundColor !== oldProps.backgroundColor) {
const backgroundColor = Array.isArray(props.backgroundColor)
? props.backgroundColor.map(c => c / 255.0).slice(0, 3)
: null;
this.setState({backgroundColor});
}
}

draw({uniforms}) {
const {sdf} = this.props;
const {backgroundColor} = this.state;
const shouldDrawBackground = Array.isArray(backgroundColor);

super.draw({
uniforms: Object.assign({}, uniforms, {
// Refer the following doc about gamma and buffer
// https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817
buffer: DEFAULT_BUFFER,
gamma: DEFAULT_GAMMA,
sdf: Boolean(sdf)
sdf: Boolean(sdf),
backgroundColor: backgroundColor || [0, 0, 0],
shouldDrawBackground
})
});
}
Expand Down
3 changes: 3 additions & 0 deletions modules/layers/src/text-layer/text-layer.js
Expand Up @@ -64,6 +64,7 @@ const defaultProps = {
sizeUnits: 'pixels',
sizeMinPixels: 0,
sizeMaxPixels: Number.MAX_SAFE_INTEGER,
backgroundColor: {type: 'color', value: null, optional: true},

characterSet: DEFAULT_CHAR_SET,
fontFamily: DEFAULT_FONT_FAMILY,
Expand Down Expand Up @@ -241,6 +242,7 @@ export default class TextLayer extends CompositeLayer {
const {data, dataDiff, scale, iconAtlas, iconMapping} = this.state;

const {
backgroundColor,
getPosition,
getColor,
getSize,
Expand All @@ -265,6 +267,7 @@ export default class TextLayer extends CompositeLayer {
sdf,
iconAtlas,
iconMapping,
backgroundColor,

_dataDiff: dataDiff && (() => dataDiff),

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions test/render/test-cases.js
Expand Up @@ -1424,6 +1424,36 @@ export const TEST_CASES = [
],
goldenImage: './test/render/golden-images/text-layer-auto-wrapping.png'
},
{
name: 'text-layer-background',
viewState: {
latitude: 37.751537058389985,
longitude: -122.42694203247012,
zoom: 11.5,
pitch: 0,
bearing: 0
},
layers: [
new TextLayer({
id: 'text-layer',
data: dataSamples.points.slice(0, 50),
opacity: 0.8,
fontFamily: 'Arial',
backgroundColor: [0.0, 255.0, 0.0, 200.0],
getText: x => `${x.PLACEMENT}-${x.YR_INSTALLED}`,
getPosition: x => x.COORDINATES,
getColor: x => [153, 0, 0],
getSize: x => 16,
getAngle: x => 0,
sizeScale: 21,
sizeUnits: 'meters',
getTextAnchor: x => 'start',
getAlignmentBaseline: x => 'center',
getPixelOffset: x => [10, 0]
})
],
goldenImage: './test/render/golden-images/text-layer-background.png'
},
{
name: 'gpu-grid-lnglat',
viewState: GRID_LAYER_INFO.viewState,
Expand Down

0 comments on commit 742cff9

Please sign in to comment.