Skip to content

Commit 579473b

Browse files
committed
Don't initialize text mesh until the font has loaded. This prevents the raycaster to intersect prematurely (fix #4742)
1 parent 2cc671e commit 579473b

File tree

2 files changed

+28
-22
lines changed

2 files changed

+28
-22
lines changed

src/components/text.js

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,11 @@ module.exports.Component = registerComponent('text', {
9191
this.shaderData = {};
9292
this.geometry = createTextGeometry();
9393
this.createOrUpdateMaterial();
94-
this.mesh = new THREE.Mesh(this.geometry, this.material);
95-
this.el.setObject3D(this.attrName, this.mesh);
9694
},
9795

9896
update: function (oldData) {
9997
var data = this.data;
10098
var font = this.currentFont;
101-
10299
if (textures[data.font]) {
103100
this.texture = textures[data.font];
104101
} else {
@@ -134,9 +131,7 @@ module.exports.Component = registerComponent('text', {
134131
this.material = null;
135132
this.texture.dispose();
136133
this.texture = null;
137-
if (this.shaderObject) {
138-
delete this.shaderObject;
139-
}
134+
if (this.shaderObject) { delete this.shaderObject; }
140135
},
141136

142137
/**
@@ -201,7 +196,7 @@ module.exports.Component = registerComponent('text', {
201196
if (!data.font) { warn('No font specified. Using the default font.'); }
202197

203198
// Make invisible during font swap.
204-
this.mesh.visible = false;
199+
if (this.mesh) { this.mesh.visible = false; }
205200

206201
// Look up font URL to use, and perform cached load.
207202
fontSrc = this.lookupFont(data.font || DEFAULT_FONT) || data.font;
@@ -217,14 +212,7 @@ module.exports.Component = registerComponent('text', {
217212
if (!fontWidthFactors[fontSrc]) {
218213
font.widthFactor = fontWidthFactors[font] = computeFontWidthFactor(font);
219214
}
220-
221-
// Update geometry given font metrics.
222-
self.updateGeometry(geometry, font);
223-
224-
// Set font and update layout.
225215
self.currentFont = font;
226-
self.updateLayout();
227-
228216
// Look up font image URL to use, and perform cached load.
229217
fontImgSrc = self.getFontImageSrc();
230218
cache.get(fontImgSrc, function () {
@@ -236,6 +224,11 @@ module.exports.Component = registerComponent('text', {
236224
texture.needsUpdate = true;
237225
textures[data.font] = texture;
238226
self.texture = texture;
227+
self.initMesh();
228+
self.currentFont = font;
229+
// Update geometry given font metrics.
230+
self.updateGeometry(geometry, font);
231+
self.updateLayout();
239232
self.mesh.visible = true;
240233
el.emit('textfontset', {font: data.font, fontObj: font});
241234
}).catch(function (err) {
@@ -248,6 +241,12 @@ module.exports.Component = registerComponent('text', {
248241
});
249242
},
250243

244+
initMesh: function () {
245+
if (this.mesh) { return; }
246+
this.mesh = new THREE.Mesh(this.geometry, this.material);
247+
this.el.setObject3D(this.attrName, this.mesh);
248+
},
249+
251250
getFontImageSrc: function () {
252251
if (this.data.fontImage) { return this.data.fontImage; }
253252
var fontSrc = this.lookupFont(this.data.font || DEFAULT_FONT) || this.data.font;
@@ -279,7 +278,7 @@ module.exports.Component = registerComponent('text', {
279278
var x;
280279
var y;
281280

282-
if (!geometry.layout) { return; }
281+
if (!mesh || !geometry.layout) { return; }
283282

284283
// Determine width to use (defined width, geometry's width, or default width).
285284
geometryComponent = el.getAttribute('geometry');

tests/components/text.test.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,21 @@ suite('text', function () {
3737
});
3838

3939
suite('multiple', function () {
40-
test('can have multiple instances', () => {
40+
test('can have multiple instances', (done) => {
4141
el.setAttribute('text__foo', {value: 'foo'});
42-
el.setAttribute('text__bar', {value: 'bar'});
43-
el.setAttribute('text__baz', {value: 'baz'});
44-
assert.ok(el.getObject3D('text') instanceof THREE.Mesh);
45-
assert.ok(el.getObject3D('text__foo') instanceof THREE.Mesh);
46-
assert.ok(el.getObject3D('text__bar') instanceof THREE.Mesh);
47-
assert.ok(el.getObject3D('text__baz') instanceof THREE.Mesh);
42+
el.addEventListener('textfontset', evt => {
43+
assert.ok(el.getObject3D('text') instanceof THREE.Mesh);
44+
assert.ok(el.getObject3D('text__foo') instanceof THREE.Mesh);
45+
el.setAttribute('text__bar', {value: 'foo'});
46+
el.addEventListener('textfontset', evt => {
47+
assert.ok(el.getObject3D('text__bar') instanceof THREE.Mesh);
48+
el.setAttribute('text__baz', {value: 'baz'});
49+
el.addEventListener('textfontset', evt => {
50+
assert.ok(el.getObject3D('text__baz') instanceof THREE.Mesh);
51+
done();
52+
});
53+
});
54+
});
4855
});
4956
});
5057

0 commit comments

Comments
 (0)