How to do GUI like text but expanding

Hi all,

I am trying to mimic the screenshots below in Babylon. The screenshots show a plane with an image texture (simple in Babylon) that has an expanding label attached to it. This was originally written in Konva and after some poking around, I am unsure how to do the expanding label. The label text expands as the camera moves closer to the image however the label font stays the same size (the containing box gets bigger showing more of the label and the opposite happens as the camera moves further away).



I’ve tried using the GUI and attaching a label which does what I want in terms of keeping the font size the same. However, that label gets further away from the mesh as the camera moves out and when the camera moves in eventually the label will be on top of the mesh. What I want is for the label to stay right under the mesh.

Below is a playground showing the general idea of trying to mimic a 2D space in 3D. But, being a new at 3D and Babylon, I’m having trouble with everything from the camera to getting text to clip with an ellipse.

https://playground.babylonjs.com/#3T5122#3

Any help much appreciated!

1 Like

Summoning our GUI expert @msDestiny14

1 Like

Let me take a look and see what I can do!

https://playground.babylonjs.com/#XCPP9Y#9080

Is this something you had more in mind? Usually, I would recommend link with mesh is the way to go because it this will scale with the zooming in and out. However I see see that you did that.

Currently trying to debug what happened in your version. I’m not quiet sure which is why I made started from scratch with your assets and camera. My guess it is the additional functionality you made with the camera input.

Let me know if you have any additional questions. :slight_smile:

1 Like

Hi! Thanks so much for taking a look!

I think we are dealing with a few different problems (my fault).

  1. The custom camera inputs are my attempt at making something like Three.js’s MapControls and can be ignored (I think)
  2. The Ellipse not showing I tracked down to setting the text.scaleX and text.scaleY. Commenting out those two lines fixed the issue (see your PG: https://playground.babylonjs.com/#XCPP9Y#9100 or in my PG with 4.2.0: https://playground.babylonjs.com/#3T5122#8)
  3. The major concern I have now is how to adjust the offset of the GUI text with its linked mesh? Right now it is hard coded to 160px but what I really want is the following:
  • Dynamically determine the offset by measuring the size of the mesh so I can place the label right under the mesh.
  • When the camera zooms in the tile will appear bigger and the linked GUI text needs to have its offset change so it sticks to the bottom of the mesh (right now the offset appears to shrink and eventually the GUI text would sit in front of the tile).
  • Similar when the camera zooms out - the linked GUI text needs to have its offset change so it sticks to the bottom of the mesh.
  • Finally, when the camera zooms in more of the linked GUI text should be shown as the rectangle’s width the GUI text is in will be expanded to fill the bottom of the mesh. Likewise, when the camera zooms out the rectangle will shrink clipping more of the GUI text.

What do you think? Even though the GUI text has a lot of properties that work with the requirements (constant font size, linked with a mesh, text wrapping) I’m wondering if it is the right tool for this job…

1 Like
  1. There’s a really nice demo for doing panning with a plane. https://www.babylonjs-playground.com/#DD2IDJ#45This actually is what makes up the panning code for the GUI editor as well. Also like this demo as well for the example you posted. https://playground.babylonjs.com/#5QBZT0#9 :slight_smile:

  2. I’m not sure I understand what you mean with the ellipse. If you would like text to clip with an ellipse shape container? Or is it just wrapping in general. Most common what I think you want is

label.textWrapping = true;

or resizeToFit = true. Some helpful hints for both. textwrapping will wrap the text to a given container size. Aka the size of the textBlock itself. resizeToFit will resize the text container w/h to fit the text.

3.To do this you will want to use the radius of the camera and come up with an offset formula. You can calculate this every frame for example: https://playground.babylonjs.com/#XCPP9Y#9102
In this I just played with the numbers. You want formula that will become a smaller offset as the radius becomes higher.

1 Like

Hmm, for #3 at least, if I understand it right, the bounding box of the mesh will have to be projected to screen coordinates in order to set the width of the label rect to the width of the mesh, and since you’d then already have the projected bounding box calculated anyway, it might be easier to use that to set the position as well.

Here’s a playground doing it that way for example.

I ended up switching to only updating when the camera’s view matrix changes to reduce the lag. It’s better now, but still can’t keep up with a fast zoom.

Also, the height of the GUI rectangle changes when its width is changed, and I can’t figure out how to get the real/current height of it, so the positioning is still slightly inaccurate…

It could maybe be a good start thou I think :slightly_smiling_face:

(Morning edits to clean up a little and to also update when the camera’s projection matrix changes to respond to window resizing)

1 Like

Hi, thanks so much for the detailed explanation and links!

Out of curiosity, is point #2 bug as the text wrapping does not seem to work if you set the scaleX and/or scaleY:

1 Like

This is awesome and exactly what I was trying to do. Thanks!

1 Like