Skip to content

Commit 5b82aca

Browse files
CANEVETGASPARDfelixpalmer
authored andcommitted
Feat: Add backgroundBorderRadius to TextLayer (#9447)
1 parent bb01fd7 commit 5b82aca

File tree

8 files changed

+296
-192
lines changed

8 files changed

+296
-192
lines changed

docs/api-reference/layers/text-layer.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ If `true`, the text always faces camera. Otherwise the text faces up (z).
198198

199199
Whether to render background for the text blocks.
200200

201+
#### `backgroundBorderRadius` (number | number[4], optional) {#backgroundBorderRadius}
202+
203+
- Default `0`
204+
205+
The border-radius of the background, a number or an array of 4 numbers.
206+
207+
+ If a number is supplied, it is the same border radius in pixel for all corners.
208+
+ If an array of 4 is supplied, it is interpreted as `[bottom_right_corner, top_right_corner, bottom_left_corner, top_left_corner]` border radius in pixel.
209+
210+
201211
#### `backgroundPadding` (number[4], optional) {#backgroundpadding}
202212

203213
- Default `[0, 0, 0, 0]`

examples/layer-browser/src/examples/core-layers.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,15 @@ const TextLayerExample = {
391391
onUpdate: (newValue, newSettings, change) => {
392392
change('backgroundPadding', [newValue, newValue]);
393393
}
394+
},
395+
backgroundBorderRadius: {type: 'compound', elements: ['borderRadius']},
396+
borderRadius: {
397+
type: 'number',
398+
min: 0,
399+
max: 100,
400+
onUpdate: (newValue, newSettings, change) => {
401+
change('backgroundBorderRadius', newValue);
402+
}
394403
}
395404
},
396405
props: {

modules/layers/src/text-layer/text-background-layer/text-background-layer-fragment.glsl.ts

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,54 @@ in vec2 dimensions;
1616
1717
out vec4 fragColor;
1818
19+
float round_rect(vec2 p, vec2 size, vec4 radii) {
20+
// Convert p and size to center-based coordinates [-0.5, 0.5]
21+
vec2 pixelPositionCB = (p - 0.5) * size;
22+
vec2 sizeCB = size * 0.5;
23+
24+
float maxBorderRadius = min(size.x, size.y) * 0.5;
25+
vec4 borderRadius = vec4(min(radii, maxBorderRadius));
26+
27+
// from https://www.shadertoy.com/view/4llXD7
28+
borderRadius.xy =
29+
(pixelPositionCB.x > 0.0) ? borderRadius.xy : borderRadius.zw;
30+
borderRadius.x = (pixelPositionCB.y > 0.0) ? borderRadius.x : borderRadius.y;
31+
vec2 q = abs(pixelPositionCB) - sizeCB + borderRadius.x;
32+
return -(min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - borderRadius.x);
33+
}
34+
35+
float rect(vec2 p, vec2 size) {
36+
vec2 pixelPosition = p * size;
37+
return min(min(pixelPosition.x, size.x - pixelPosition.x),
38+
min(pixelPosition.y, size.y - pixelPosition.y));
39+
}
40+
41+
vec4 get_stroked_fragColor(float dist) {
42+
float isBorder = smoothedge(dist, vLineWidth);
43+
return mix(vFillColor, vLineColor, isBorder);
44+
}
45+
1946
void main(void) {
2047
geometry.uv = uv;
2148
22-
vec2 pixelPosition = uv * dimensions;
23-
if (textBackground.stroked) {
24-
float distToEdge = min(
25-
min(pixelPosition.x, dimensions.x - pixelPosition.x),
26-
min(pixelPosition.y, dimensions.y - pixelPosition.y)
27-
);
28-
float isBorder = smoothedge(distToEdge, vLineWidth);
29-
fragColor = mix(vFillColor, vLineColor, isBorder);
49+
if (textBackground.borderRadius != vec4(0.0)) {
50+
float distToEdge = round_rect(uv, dimensions, textBackground.borderRadius);
51+
if (textBackground.stroked) {
52+
fragColor = get_stroked_fragColor(distToEdge);
53+
} else {
54+
fragColor = vFillColor;
55+
}
56+
// add border radius
57+
float shapeAlpha = smoothedge(-distToEdge, 0.0);
58+
fragColor.a *= shapeAlpha;
3059
} else {
31-
fragColor = vFillColor;
60+
if (textBackground.stroked) {
61+
float distToEdge = rect(uv, dimensions);
62+
fragColor = get_stroked_fragColor(distToEdge);
63+
} else {
64+
fragColor = vFillColor;
65+
}
3266
}
33-
3467
DECKGL_FILTER_COLOR(fragColor, geometry);
3568
}
3669
`;

modules/layers/src/text-layer/text-background-layer/text-background-layer-uniforms.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ uniform textBackgroundUniforms {
1010
float sizeScale;
1111
float sizeMinPixels;
1212
float sizeMaxPixels;
13+
vec4 borderRadius;
1314
vec4 padding;
1415
highp int sizeUnits;
1516
bool stroked;
@@ -21,6 +22,7 @@ export type TextBackgroundProps = {
2122
sizeScale: number;
2223
sizeMinPixels: number;
2324
sizeMaxPixels: number;
25+
borderRadius: [number, number, number, number];
2426
padding: [number, number, number, number];
2527
sizeUnits: number;
2628
stroked: boolean;
@@ -35,6 +37,7 @@ export const textBackgroundUniforms = {
3537
sizeScale: 'f32',
3638
sizeMinPixels: 'f32',
3739
sizeMaxPixels: 'f32',
40+
borderRadius: 'vec4<f32>',
3841
padding: 'vec4<f32>',
3942
sizeUnits: 'i32',
4043
stroked: 'f32'

modules/layers/src/text-layer/text-background-layer/text-background-layer.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type _TextBackgroundLayerProps<DataT> = {
2929
sizeMinPixels?: number;
3030
sizeMaxPixels?: number;
3131

32+
borderRadius?: number | [number, number, number, number];
3233
padding?: [number, number] | [number, number, number, number];
3334

3435
getPosition?: Accessor<DataT, Position>;
@@ -51,6 +52,7 @@ const defaultProps: DefaultProps<TextBackgroundLayerProps> = {
5152
sizeMinPixels: 0,
5253
sizeMaxPixels: Number.MAX_SAFE_INTEGER,
5354

55+
borderRadius: {type: 'object', value: 0},
5456
padding: {type: 'array', value: [0, 0, 0, 0]},
5557

5658
getPosition: {type: 'accessor', value: (x: any) => x.position},
@@ -142,16 +144,21 @@ export default class TextBackgroundLayer<DataT = any, ExtraPropsT extends {} = {
142144
draw({uniforms}) {
143145
const {billboard, sizeScale, sizeUnits, sizeMinPixels, sizeMaxPixels, getLineWidth} =
144146
this.props;
145-
let {padding} = this.props;
147+
let {padding, borderRadius} = this.props;
146148

147149
if (padding.length < 4) {
148150
padding = [padding[0], padding[1], padding[0], padding[1]];
149151
}
150152

153+
if (!Array.isArray(borderRadius)) {
154+
borderRadius = [borderRadius, borderRadius, borderRadius, borderRadius];
155+
}
156+
151157
const model = this.state.model!;
152158
const textBackgroundProps: TextBackgroundProps = {
153159
billboard,
154160
stroked: Boolean(getLineWidth),
161+
borderRadius,
155162
padding: padding as [number, number, number, number],
156163
sizeUnits: UNIT[sizeUnits],
157164
sizeScale,

modules/layers/src/text-layer/text-layer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ type _TextLayerProps<DataT> = {
8787
* @default 0
8888
*/
8989
getBorderWidth?: Accessor<DataT, number>;
90+
/** The border radius of the background.
91+
* If a number is supplied, it is the same border radius in pixel for all corners.
92+
* If an array of 4 is supplied, it is interpreted as `[bottom_right_corner, top_right_corner, bottom_left_corner, top_left_corner]` border radius in pixel.
93+
* @default 0
94+
*/
95+
backgroundBorderRadius?: number | [number, number, number, number];
9096
/**
9197
* The padding of the background..
9298
* If an array of 2 is supplied, it is interpreted as `[padding_x, padding_y]` in pixels.
@@ -194,6 +200,7 @@ const defaultProps: DefaultProps<TextLayerProps> = {
194200
getBackgroundColor: {type: 'accessor', value: [255, 255, 255, 255]},
195201
getBorderColor: {type: 'accessor', value: DEFAULT_COLOR},
196202
getBorderWidth: {type: 'accessor', value: 0},
203+
backgroundBorderRadius: {type: 'object', value: 0},
197204
backgroundPadding: {type: 'array', value: [0, 0, 0, 0]},
198205

199206
characterSet: {type: 'object', value: DEFAULT_FONT_SETTINGS.characterSet},
@@ -478,6 +485,7 @@ export default class TextLayer<DataT = any, ExtraPropsT extends {} = {}> extends
478485
getBackgroundColor,
479486
getBorderColor,
480487
getBorderWidth,
488+
backgroundBorderRadius,
481489
backgroundPadding,
482490
background,
483491
billboard,
@@ -503,6 +511,7 @@ export default class TextLayer<DataT = any, ExtraPropsT extends {} = {}> extends
503511
getFillColor: getBackgroundColor,
504512
getLineColor: getBorderColor,
505513
getLineWidth: getBorderWidth,
514+
borderRadius: backgroundBorderRadius,
506515
padding: backgroundPadding,
507516

508517
// props shared with characters layer
85.8 KB
Loading

0 commit comments

Comments
 (0)