Skip to content

Commit

Permalink
Update text plane size following text mutation (fixes #2764). (#5357)
Browse files Browse the repository at this point in the history
The plane width/height was being calculated when the text value was first set,
but would not update when the text changed.

Documentation has also been updated to advise using `0` rather than `auto`
for autoscaling behavior.  This is based on the the comment
[here](#2837 (comment))
suggesting that `auto` is not a valid value for geometry (NaN is falsy, so it
happened to still work).
  • Loading branch information
brycethomas authored Oct 19, 2023
1 parent 4858281 commit d8ade4f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
6 changes: 3 additions & 3 deletions docs/components/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,22 +241,22 @@ geometry component's `width`, do not specify a `width` for the text component:

```html
<a-entity
geometry="primitive: plane; width: 4; height: auto"
geometry="primitive: plane; width: 4; height: 0"
material="color: blue"
text="value: This text will be 4 units wide."></a-entity>
```

#### Scaling Geometry to Fit Text

To have the geometry automatically scale with the text, set the geometry
component's `width` and `height` properties to `auto`, and set the text
component's `width` and `height` properties to `0`, and set the text
component's `width` as desired. In this example, the plane's `width` will be
set to 4 units, and its `height` will be set to match the actual height of the
text:

```html
<a-entity
geometry="primitive: plane; height: auto; width: auto"
geometry="primitive: plane; height: 0; width: 0"
material="color: blue"
text="width: 4; value: This text will be 4 units wide."></a-entity>
```
Expand Down
10 changes: 8 additions & 2 deletions src/components/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module.exports.Component = registerComponent('text', {
this.shaderData = {};
this.geometry = createTextGeometry();
this.createOrUpdateMaterial();
this.explicitGeoDimensionsChecked = false;
},

update: function (oldData) {
Expand Down Expand Up @@ -302,8 +303,13 @@ module.exports.Component = registerComponent('text', {
// Update geometry dimensions to match text layout if width and height are set to 0.
// For example, scales a plane to fit text.
if (geometryComponent && geometryComponent.primitive === 'plane') {
if (!geometryComponent.width) { el.setAttribute('geometry', 'width', width); }
if (!geometryComponent.height) { el.setAttribute('geometry', 'height', height); }
if (!this.explicitGeoDimensionsChecked) {
this.explicitGeoDimensionsChecked = true;
this.hasExplicitGeoWidth = !!geometryComponent.width;
this.hasExplicitGeoHeight = !!geometryComponent.height;
}
if (!this.hasExplicitGeoWidth) { el.setAttribute('geometry', 'width', width); }
if (!this.hasExplicitGeoHeight) { el.setAttribute('geometry', 'height', height); }
}

// Calculate X position to anchor text left, center, or right.
Expand Down
46 changes: 46 additions & 0 deletions tests/components/text.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,52 @@ suite('text', function () {
assert.ok(el.getAttribute('geometry').height);
});

test('autoscales mesh to text change', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 0, width: 0});
assert.equal(el.getAttribute('geometry').width, 0);
assert.equal(el.getAttribute('geometry').height, 0);

el.setAttribute('text', {width: 10, value: 'a'});
assert.equal(el.getAttribute('geometry').width, 10);
var heightBefore = el.getAttribute('geometry').height;
var widthBefore = el.getAttribute('geometry').width;
assert.ok(heightBefore);

el.setAttribute('text', {value: 'a\nb'});
var heightAfter = el.getAttribute('geometry').height;
var widthAfter = el.getAttribute('geometry').width;
assert.equal(widthBefore, widthAfter);
assert.isAbove(heightAfter, heightBefore);
});

test('does not autoscale mesh with explicit width', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 0, width: 1});
assert.equal(el.getAttribute('geometry').width, 1);
assert.equal(el.getAttribute('geometry').height, 0);

el.setAttribute('text', {width: 10, value: 'a'});
assert.equal(el.getAttribute('geometry').width, 1);
assert.isAbove(el.getAttribute('geometry').height, 0);

el.setAttribute('text', {value: 'a\nb'});
assert.equal(el.getAttribute('geometry').width, 1);
assert.isAbove(el.getAttribute('geometry').height, 0);
});

test('does not autoscale mesh with explicit height', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 1, width: 0});
assert.equal(el.getAttribute('geometry').width, 0);
assert.equal(el.getAttribute('geometry').height, 1);

el.setAttribute('text', {width: 10, value: 'a'});
assert.isAbove(el.getAttribute('geometry').width, 0);
assert.equal(el.getAttribute('geometry').height, 1);

el.setAttribute('text', {value: 'a\nb'});
assert.isAbove(el.getAttribute('geometry').width, 0);
assert.equal(el.getAttribute('geometry').height, 1);
});

test('autoscales text to mesh', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 1, width: 50000});
el.setAttribute('text', {value: 'a', width: 0});
Expand Down

0 comments on commit d8ade4f

Please sign in to comment.