简体   繁体   English

THREE.js如何停止2D画布制成的纹理中的文本截断

[英]THREE.js How to stop truncation of text in texture made from 2D canvas

It seems quite common for people to use this 2d canvas texture method for producing text billboards, sprites, overlays in THREE.js scenes as an alternative to making textures from imported image files eg Lee Stemkoski's example . 人们似乎很普遍地使用这种2d画布纹理方法在THREE.js场景中生成文本广告牌,子画面,覆盖图,而不是从导入的图像文件中生成纹理的替代方法,例如Lee Stemkoski的示例

However when I try such method for text strings longer than a few characters the text in the finished graphic object is truncated. 但是,当我针对长度超过几个字符的文本字符串尝试这种方法时,完成的图形对象中的文本将被截断。

Here is a JSFiddle 这是一个JSFiddle

Here is the relevant code 这是相关的代码

function F_Text_Plane_Make_wo_box(text)

{
    var canvas1 = document.createElement('canvas');
    var context1 = canvas1.getContext('2d');
    context1.font = "Bold 40px Arial";
    context1.fillStyle = "rgba(155,0,200,0.95)";
    context1.fillText(text, 0, 50);

    var texture1 = new THREE.Texture(canvas1);
    texture1.needsUpdate = true;

    var material1 = new THREE.MeshBasicMaterial
    ( { map: texture1, side:THREE.DoubleSide } );
    material1.transparent = true;

    var mesh1 = new THREE.Mesh(
        new THREE.PlaneGeometry(canvas1.width, canvas1.height),
        material1
    );
    return mesh1;
}

It occurs in Chrome, Opera and Firefox on Windows7 laptop. 它发生在Windows7笔记本电脑上的Chrome,Opera和Firefox中。

UPDATE UPDATE

Thanks to West Langley for clarifying matters. 感谢West Langley澄清问题。 It appears that we can't easily and automatically construct a plane which contains the supplied text string and no trailing white space. 看来我们不能轻松,自动地构建一个包含提供的文本字符串且没有尾随空白的平面。 This limitation can be worked around using transparency or a fixed-width destination container. 可以使用透明性或固定宽度的目标容器来解决此限制。

Here is a JSFiddle 这是一个JSFiddle

Here is relevant code 这是相关的代码

//=============================================================================
function F_Text_onto_Plane(text, Tbox_width, Tbox_depth)

{

    var canvas1 = document.createElement('canvas');
    var context1 = canvas1.getContext('2d');

    canvas1.width = Tbox_width; canvas1.height = Tbox_depth;

    context1.font = "Bold 40px Arial"; //... font as big and simple as possible so graphics look smooth

    var metric = context1.measureText(text);
    var text_len_pixels = metric.width;

    //------------ Backing Rectangle ------------
    context1.fillStyle = "rgba(255,255,255,0.95)"; //... White
    //..x1,y1, x2,y2 origin in top left corner x increasing rightwards, y increasing downwards.  
    context1.fillRect(0,0, Tbox_width, Tbox_depth);  //... rectangle matches the Tbox_width and Tbox_depth

    context1.fillStyle = "rgba(255,255,0,0.95)"; //... Yellow, probably change to white in practice.
    context1.fillRect(0,0,5+text_len_pixels+5,Tbox_depth);  //... very good fit to the particular text

    //------------- Paint the Text onto canvas ----------------
    context1.fillStyle = "rgba(0,0,0,1)";//... Black.
    context1.fillText(text , 0+5, Tbox_depth-5);//... text string, start_x, start_y (start point is bottom left of first character).

    //------------------------------------------------
    //... canvas contents will be used for a texture
    //... note this takes the everything within the canvas area, including the canvas background.
    var texture1 = new THREE.Texture(canvas1);
    texture1.needsUpdate = true;

    var material1 = new THREE.MeshLambertMaterial( { map: texture1, side:THREE.DoubleSide } );
    material1.transparent = true;

    var mesh1 = new THREE.Mesh(
        new THREE.PlaneGeometry(Tbox_width, Tbox_depth),
        material1 );

    //... can scale the plane e.g.  mesh1.scale.set(100,50,1.0);
    //... alert ("Checkout: http://stackoverflow.com/questions/4532166/how-to-capture-a-section-of-a-canvas-to-a-bitmap?lq=1");
    //... can use .lookat to make plane face a single camera in the scene.
    //... can use THREE.js Sprite to make plane look at all cameras in the scene.

    return mesh1;


}

You need to set the canvas width: 您需要设置画布宽度:

var canvas1 = document.createElement( 'canvas' );
canvas1.width = 512;
canvas1.height = 64;

var texture1 = new THREE.Texture( canvas1 );
texture1.needsUpdate = true;

var material1 = new THREE.MeshLambertMaterial( {  map: texture1, side:THREE.DoubleSide, transparent = true } );

Now, when you create your mesh geometry, you specify its size in world units, not in pixels: 现在,当您创建网格几何时,可以以世界单位而不是像素指定其大小:

var mesh1 = new THREE.Mesh( new THREE.PlaneGeometry( 1024, 128 ), material1 );

three.js r.70 three.js r.70

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM