43 - 3.js Notes - Create Text Tags Using Sprite Wizards

Keywords: Attribute Javascript html5

Sprite in computer graphics refers to the two-dimensional animation and image contained in the scene, that is, sprite is a plane always facing the camera, similar to billboards, without the concept of z axis, and Sprite does not accept shadows.
Example: http://ithanmang.com/threeJs/home/201808/20180815/03-sprite-text.html

The example creates a three-dimensional coordinate axis, draws fonts using canvas and adds them as textures to sprite map attributes to create a two-dimensional font label that displays information and can scale and move with the coordinate axis.

Firstly, the rounded rectangle is drawn by canvas, and the size of the rectangle varies with the number of words. The knowledge about canvas can be obtained. http://www.runoob.com/html/html5-canvas.html Study.

/* Draw rounded rectangle */
    function roundRect(ctx, x, y, w, h, r) {

        ctx.beginPath();
        ctx.moveTo(x+r, y);
        ctx.lineTo(x+w-r, y);
        ctx.quadraticCurveTo(x+w, y, x+w, y+r);
        ctx.lineTo(x+w, y+h-r);
        ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
        ctx.lineTo(x+r, y+h);
        ctx.quadraticCurveTo(x, y+h, x, y+h-r);
        ctx.lineTo(x, y+r);
        ctx.quadraticCurveTo(x, y, x+r, y);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();

    }

Then, draw the text wizard and return to the created sprite

/* Creating Font Wizard */
function makeTextSprite(message, parameters) {

    if ( parameters === undefined ) parameters = {};

    let fontface = parameters.hasOwnProperty("fontface") ?
        parameters["fontface"] : "Arial";

    /* font size */
    let fontsize = parameters.hasOwnProperty("fontsize") ?
        parameters["fontsize"] : 18;

    /* Border thickness */
    let borderThickness = parameters.hasOwnProperty("borderThickness") ?
        parameters["borderThickness"] : 4;

    /* Border color */
    let borderColor = parameters.hasOwnProperty("borderColor") ?
        parameters["borderColor"] : { r:0, g:0, b:0, a:1.0 };

    /* background color */
    let backgroundColor = parameters.hasOwnProperty("backgroundColor") ?
        parameters["backgroundColor"] : { r:255, g:255, b:255, a:1.0 };

    /* Create canvas */
    let canvas = document.createElement('canvas');
    let context = canvas.getContext('2d');

    /* font-weight */
    context.font = "Bold " + fontsize + "px " + fontface;

    /* Getting the size of the text depends on the size of the text. */
    let metrics = context.measureText( message );
    let textWidth = metrics.width;

    /* background color */
    context.fillStyle   = "rgba(" + backgroundColor.r + "," + backgroundColor.g + ","
        + backgroundColor.b + "," + backgroundColor.a + ")";

    /* border color */
    context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + ","
        + borderColor.b + "," + borderColor.a + ")";
    context.lineWidth = borderThickness;

    /* Draw rounded rectangle */
    roundRect(context, borderThickness/2, borderThickness/2, textWidth + borderThickness, fontsize * 1.4 + borderThickness, 6);

    /* Font color */
    context.fillStyle = "rgba(0, 0, 0, 1.0)";
    context.fillText( message, borderThickness, fontsize + borderThickness);

    /* Canvas content for texture mapping */
    let texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;

    let spriteMaterial = new THREE.SpriteMaterial({ map: texture } );
    let sprite = new THREE.Sprite( spriteMaterial );

    console.log(sprite.spriteMaterial);

    /* Scaling ratio */
    sprite.scale.set(10,5,0);

    return sprite;

}

sprite can be used to display model information, and div and flat can also be used to display.

Complete sample code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sprite Particles (Elves) Create Text</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;/* Overflow hiding */
        }
    </style>
    <script src="../../libs/build/three-r93.js"></script>
    <script src="../../libs/examples/js/Detector.js"></script>
    <script src="../../libs/examples/js/libs/dat.gui.min.js"></script>
    <script src="../../libs/examples/js/libs/stats.min.js"></script>
    <script src="../../libs/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script>

    let scene, camera, renderer, controls, points;
    let stats = initStats();

    /* scene */
    function initScene() {

        scene = new THREE.Scene();

    }

    /* camera */
    function initCamera() {

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
        camera.position.set(20, 10, 50);
        camera.lookAt(new THREE.Vector3(0, 0, 0));

    }

    /* Renderer */
    function initRender() {

        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setSize(window.innerWidth, window.innerHeight);

        document.body.appendChild(renderer.domElement);

    }

    /* lighting */
    function initLight() {



    }

    /* Controller */
    function initControls() {

        controls = new THREE.OrbitControls(camera, renderer.domElement);

        /* Property parameter default */

    }

    /* Content in the scene */
    function initContent() {

        let dirX = new THREE.Vector3( 1, 0, 0 );
        let dirY = new THREE.Vector3( 0, 1, 0 );
        let dirZ = new THREE.Vector3( 0, 0, 1 );

        let origin = new THREE.Vector3( 0, 0, 0 );
        let length = 10;

        let arrowHelperX = new THREE.ArrowHelper( dirX, origin, length, 0xff0000 );
        let arrowHelperY = new THREE.ArrowHelper( dirY, origin, length, 0x00ff00 );
        let arrowHelperZ = new THREE.ArrowHelper( dirZ, origin, length, 0x0000ff );
        scene.add( arrowHelperX );
        scene.add( arrowHelperY );
        scene.add( arrowHelperZ );

        /* origin */
        let spriteOrigin = makeTextSprite( " vector3(0, 0, 0) ",
            {
                fontsize: 20,
                borderColor: {r:255, g:0, b:0, a:0.4},/* Border black */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* background color */
            } );
        spriteOrigin.center = new THREE.Vector2(0, 0);
        scene.add( spriteOrigin );
        spriteOrigin.position.set(0, -5, 0);

        let spriteY = makeTextSprite( "Y",
            {
                fontsize: 20,
                borderColor: {r:255, g:0, b:0, a:0.4},/* Border black */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* background color */
            } );
        spriteY.center = new THREE.Vector2(0, 0);
        scene.add( spriteY );
        spriteY.position.set(0, 6, 0);

        let spriteX = makeTextSprite( "X",
            {
                fontsize: 20,
                borderColor: {r:255, g:0, b:0, a:0.4},/* Border black */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* background color */
            } );
        spriteX.center = new THREE.Vector2(0, 0);
        scene.add( spriteX );
        spriteX.position.set(10, -5, 0);

        let spriteZ = makeTextSprite( "Z",
            {
                fontsize: 20,
                borderColor: {r:255, g:0, b:0, a:0.4},/* Border black */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* background color */
            } );
        spriteZ.center = new THREE.Vector2(0, 0);
        scene.add( spriteZ );
        spriteZ.position.set(0, -5, 10);

    }

    /* Creating Font Wizard */
    function makeTextSprite(message, parameters) {

        if ( parameters === undefined ) parameters = {};

        let fontface = parameters.hasOwnProperty("fontface") ?
            parameters["fontface"] : "Arial";

        /* font size */
        let fontsize = parameters.hasOwnProperty("fontsize") ?
            parameters["fontsize"] : 18;

        /* Border thickness */
        let borderThickness = parameters.hasOwnProperty("borderThickness") ?
            parameters["borderThickness"] : 4;

        /* Border color */
        let borderColor = parameters.hasOwnProperty("borderColor") ?
            parameters["borderColor"] : { r:0, g:0, b:0, a:1.0 };

        /* background color */
        let backgroundColor = parameters.hasOwnProperty("backgroundColor") ?
            parameters["backgroundColor"] : { r:255, g:255, b:255, a:1.0 };

        /* Create canvas */
        let canvas = document.createElement('canvas');
        let context = canvas.getContext('2d');

        /* font-weight */
        context.font = "Bold " + fontsize + "px " + fontface;

        /* Getting the size of the text depends on the size of the text. */
        let metrics = context.measureText( message );
        let textWidth = metrics.width;

        /* background color */
        context.fillStyle   = "rgba(" + backgroundColor.r + "," + backgroundColor.g + ","
            + backgroundColor.b + "," + backgroundColor.a + ")";

        /* border color */
        context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + ","
            + borderColor.b + "," + borderColor.a + ")";
        context.lineWidth = borderThickness;

        /* Draw rounded rectangle */
        roundRect(context, borderThickness/2, borderThickness/2, textWidth + borderThickness, fontsize * 1.4 + borderThickness, 6);

        /* Font color */
        context.fillStyle = "rgba(0, 0, 0, 1.0)";
        context.fillText( message, borderThickness, fontsize + borderThickness);

        /* Canvas content for texture mapping */
        let texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;

        let spriteMaterial = new THREE.SpriteMaterial({ map: texture } );
        let sprite = new THREE.Sprite( spriteMaterial );

        console.log(sprite.spriteMaterial);

        /* Scaling ratio */
        sprite.scale.set(10,5,0);

        return sprite;

    }

    /* Draw rounded rectangle */
    function roundRect(ctx, x, y, w, h, r) {

        ctx.beginPath();
        ctx.moveTo(x+r, y);
        ctx.lineTo(x+w-r, y);
        ctx.quadraticCurveTo(x+w, y, x+w, y+r);
        ctx.lineTo(x+w, y+h-r);
        ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
        ctx.lineTo(x+r, y+h);
        ctx.quadraticCurveTo(x, y+h, x, y+h-r);
        ctx.lineTo(x, y+r);
        ctx.quadraticCurveTo(x, y, x+r, y);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();

    }


    /* Performance plug-ins */
    function initStats() {

        let stats = new Stats();

        document.body.appendChild(stats.domElement);

        return stats;

    }

    /* Window change trigger */
    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);

    }

    /* Data updating */
    function update() {

        stats.update();

    }

    /* Initialization */
    function init() {

        initScene();
        initCamera();
        initRender();
        initLight();
        initControls();
        initContent();

        /* Monitoring events */
        window.addEventListener('resize', onWindowResize, false);

    }

    /* Circular rendering */
    function animate() {

        requestAnimationFrame(animate);
        renderer.render(scene, camera);
        update();

    }

    /* Initial loading */
    (function () {
        console.log("three init start...");

        init();
        animate();

        console.log("three init send...");
    })();

</script>
</body>
</html>

Posted by blinks on Sun, 03 Feb 2019 21:21:16 -0800