diff --git a/docs/api-reference/layers/geojson-layer.md b/docs/api-reference/layers/geojson-layer.md index 5a076a19abf..b0df1228814 100644 --- a/docs/api-reference/layers/geojson-layer.md +++ b/docs/api-reference/layers/geojson-layer.md @@ -448,6 +448,7 @@ The following props are forwarded to a `TextLayer` if `pointType` is `'text'`. | `textFontWeight` | `'normal'` | [fontWeight](./text-layer.md#fontweight) | | `textLineHeight` | `1` | [lineHeight](./text-layer.md#lineheight) | | `textMaxWidth` | `-1` | [maxWidth](./text-layer.md#maxwidth) | +| `getTextMaxWidth` | `-1` | [getMaxWidth](./text-layer.md#getmaxwidth) | | `textWordBreak` | `'break-word'` | [wordBreak](./text-layer.md#wordbreak) | | `textBackground` | `false` | [background](./text-layer.md#background) | | `textBackgroundPadding` | `[0, 0]` | [backgroundPadding](./text-layer.md#backgroundpadding) | diff --git a/docs/api-reference/layers/text-layer.md b/docs/api-reference/layers/text-layer.md index bfc29b22085..d14a589aa22 100644 --- a/docs/api-reference/layers/text-layer.md +++ b/docs/api-reference/layers/text-layer.md @@ -273,6 +273,8 @@ Available options are `break-all` and `break-word`. A valid `maxWidth` has to be A unitless number that will be multiplied with the current text size to set the width limit of a string. If specified, when the text is longer than the width limit, it will be wrapped into multiple lines using the strategy of `wordBreak`. +Use the `getMaxWidth` accessor to supply this value per object. + For example, `maxWidth: 10.0` used with `getSize: 12` is roughly the equivalent of `max-width: 120px` in CSS. #### `outlineWidth` (number, optional) {#outlinewidth} @@ -312,6 +314,12 @@ The font size of each text label, in units specified by `sizeUnits` (default pix * If a number is provided, it is used as the size for all objects. * If a function is provided, it is called on each object to retrieve its size. +#### `getMaxWidth` ([Accessor](../../developer-guide/using-layers.md#accessors), optional) {#getmaxwidth} + +* Default: `-1` + +Method called to retrieve the width limit of each text label. The value uses the same unit as `maxWidth`. A negative value disables the limit for the object. + #### `getColor` ([Accessor<Color>](../../developer-guide/using-layers.md#accessors), optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square") {#getcolor} diff --git a/modules/layers/src/geojson-layer/sub-layer-map.ts b/modules/layers/src/geojson-layer/sub-layer-map.ts index 08aaa79dd7f..3500f07f426 100644 --- a/modules/layers/src/geojson-layer/sub-layer-map.ts +++ b/modules/layers/src/geojson-layer/sub-layer-map.ts @@ -68,6 +68,7 @@ export const POINT_LAYER = { textFontWeight: 'fontWeight', textLineHeight: 'lineHeight', textMaxWidth: 'maxWidth', + getTextMaxWidth: 'getMaxWidth', textOutlineColor: 'outlineColor', textOutlineWidth: 'outlineWidth', textWordBreak: 'wordBreak', diff --git a/modules/layers/src/text-layer/text-layer.ts b/modules/layers/src/text-layer/text-layer.ts index a69b5dfedbe..5f8c4a0a3f8 100644 --- a/modules/layers/src/text-layer/text-layer.ts +++ b/modules/layers/src/text-layer/text-layer.ts @@ -143,6 +143,11 @@ type _TextLayerProps = { * @default -1 */ maxWidth?: number; + /** + * Per-object width limit accessor. Returns the same unit as `maxWidth`. + * @default -1 + */ + getMaxWidth?: Accessor; /** * Label text accessor */ @@ -214,6 +219,7 @@ const defaultProps: DefaultProps = { // auto wrapping options wordBreak: 'break-word', maxWidth: {type: 'number', value: -1}, + getMaxWidth: {type: 'accessor', value: -1}, getText: {type: 'accessor', value: (x: any) => x.text}, getPosition: {type: 'accessor', value: (x: any) => x.position}, @@ -274,7 +280,10 @@ export default class TextLayer extends fontChanged || props.lineHeight !== oldProps.lineHeight || props.wordBreak !== oldProps.wordBreak || - props.maxWidth !== oldProps.maxWidth; + props.maxWidth !== oldProps.maxWidth || + props.getMaxWidth !== oldProps.getMaxWidth || + (changeFlags.updateTriggersChanged && + (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getMaxWidth)); if (styleChanged) { this.setState({ @@ -387,14 +396,25 @@ export default class TextLayer extends const {fontAtlasManager} = this.state; const iconMapping = fontAtlasManager.mapping!; const getText = this.state.getText!; - const {wordBreak, lineHeight, maxWidth} = this.props; + const {wordBreak, lineHeight, maxWidth, getMaxWidth} = this.props; + + let objectMaxWidth = maxWidth; + const maxWidthAccessor = getMaxWidth; + if (typeof maxWidthAccessor === 'function') { + const value = maxWidthAccessor(object, objectInfo); + if (Number.isFinite(value) && value >= 0) { + objectMaxWidth = value; + } + } else if (Number.isFinite(maxWidthAccessor) && maxWidthAccessor >= 0) { + objectMaxWidth = maxWidthAccessor; + } const paragraph = getText(object, objectInfo) || ''; return transformParagraph( paragraph, lineHeight, wordBreak, - maxWidth * fontAtlasManager.props.fontSize, + objectMaxWidth * fontAtlasManager.props.fontSize, iconMapping ); } @@ -549,6 +569,7 @@ export default class TextLayer extends getText: updateTriggers.getText, getTextAnchor: updateTriggers.getTextAnchor, getAlignmentBaseline: updateTriggers.getAlignmentBaseline, + getMaxWidth: updateTriggers.getMaxWidth, styleVersion } } @@ -609,6 +630,7 @@ export default class TextLayer extends getIconOffsets: { getTextAnchor: updateTriggers.getTextAnchor, getAlignmentBaseline: updateTriggers.getAlignmentBaseline, + getMaxWidth: updateTriggers.getMaxWidth, styleVersion } }