Jump to content

Dynamic, non-square text labels with background


Numa
 Share

Recommended Posts

Hi there, 

I'm trying to reproduce this (the label, I'll deal with the line+dot later). I'm fine with either 2D canvas (bGUI style) or 3d textured planes.

 32bbfdcacb.jpg

 

I've looked at a bunch of solutions but so far nothing has worked properly:

1. castorGUI seems great but if I hover over an element while dragging the camera around, I lose focus. (is there a way to prevent that?)

2. bGUI doesn't have that problem but:

a. the guiText doesn't seem to support background colors

b. the guiPanel doesn't seem to support dynamic textures

3. babylon sprite manager sort of works I'm not really sure how to get a non-square texture without stretching the text.

 

What do you reckon is the best way to go? I'm sure I missed some sweet parameter or undocumented function :)

 

Link to comment
Share on other sites

1 hour ago, Numa said:

castorGUI seems great but if I hover over an element while dragging the camera around, I lose focus. (is there a way to prevent that?)

Hi,

I have no solution for this because CastorGUI is a layer on top of the canvas. if the mouse is over an element of the GUI, it is no longer on the canvas.

Maybe he is a soution but I still have not figure out how to get around this. Maybe one day...

1 hour ago, Numa said:

the guiText doesn't seem to support background colors

I could probably add it in the next day.

Link to comment
Share on other sites

@dad72 oh thanks! yeah, if you could add it that would be super cool!

---

Ok I got it to work by drawing text on a transparent square texture, and filling only the relevant portion of the canvas with a background color depending on how many lines of text I have. It was quite easy, I didn't realize I could do that.

Here is the code in case someone else runs into that, I saw a fair amount of posts on that topic:

var MakeTextSprite = function (object, scene)
{
    // Make a dynamic texture
    var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", 512, scene, true);
    dynamicTexture.hasAlpha = true;

    var textureContext = dynamicTexture.getContext();
    textureContext.save();
    textureContext.textAlign = "center";
    textureContext.font = "58px Calibri";

    // Some magic numbers, chose your own
    var lineHeight = 70;
    var lineWidth = 500;
    var fontHeight = 53;
    var offset = 10; // space between top/bottom borders and actual text
    var text = object.Description; // Text to display

    var textHeight = fontHeight + offset;
    var labelHeight = numberOfLines * lineHeight + (2 * offset);

    // Background
    textureContext.fillStyle = "white";
    textureContext.fillRect(0, 0, dynamicTexture.getSize().width, labelHeight);

    // text
    textureContext.fillStyle = "black";
    wrapText(textureContext, text, dynamicTexture.getSize().width / 2, textHeight, lineWidth, lineHeight);

    textureContext.restore();
    dynamicTexture.update(false);

    // Create the sprite
    var spriteManager = new BABYLON.SpriteManager("sm", "", 2, 512, scene);
    spriteManager._spriteTexture = dynamicTexture;
    spriteManager._spriteTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    spriteManager._spriteTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
    var sprite = new BABYLON.Sprite("textSprite", spriteManager);

    return sprite;
};

// Text wrapping
function wrapText(context, text, x, y, maxWidth, lineHeight) {
    var words = text.split(' ');
    var line = '';
    var numberOfLines = 0;

    for (var n = 0; n < words.length; n++) {
        var testLine = line + words[n] + ' ';
        var metrics = context.measureText(testLine);
        var testWidth = metrics.width;

        if (testWidth > maxWidth && n > 0) {
            context.fillText(line, x, y);
            line = words[n] + ' ';
            y += lineHeight;
            numberOfLines++;
        }
        else {
            line = testLine;
        }
    }
    context.fillText(line, x, y);

    return numberOfLines;
}

 

Link to comment
Share on other sites

Ok I thought I had it but I don't.

here is a playground, I have 2 problems:

1. the blue part is just for this example, and shows the real size of the texture, the white part is what the label will look like. As you can see the red line points to the center of the whole texture, how can I get it to point at the center of the white part? (it's a mix of world and screen dimensions, what's a good way to achieve that?) (see lines 34-38)

2. I want the label to have the same size at all times, is there a way I can change its size depending on the camera zoom or something like that? Maybe I should stick to 2d to avoid all that?

http://www.babylonjs-playground.com/#1EJNKR#2

Thanks :D

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...