【问题标题】:React Three Fiber equivalent of scene.add() - 2D Text Sprites with React Three Fiber反应三纤维等效于 scene.add() - 使用反应三纤维的 2D 文本精灵
【发布时间】:2021-04-18 11:18:50
【问题描述】:

关注这个:three.js 2D Text sprite labels

我找到了如何在three.js 上制作二维文本精灵,我现在需要它来反应三纤维。

我的 index.js 上有这个:

   <Canvas 
        gl={{}}
          orthographic camera={{zoom: 20, position: [28, 22, 26]}}
          color={'#FF3333'}
          >
          <ambientLight />
          <pointLight position={[0, 10, 30]} />
          <Box   className="boxMesh" color={'#FF3333'} active={active} setActive={setActive} position={[-1, 0, 10]} />
          <Text position={[-4, -4, 10]}   />
          <Controls />
        </Canvas>

Box 工作正常,文本我不知道如何在反应三纤维 Text.js 中转换该代码


function Text(props) {
    // This reference will give us direct access to the mesh
    const mesh = useRef()

    function makeTextSprite( message, parameters )
    {
        if ( parameters === undefined ) parameters = {};
        var fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "Arial";
        var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18;
        var borderThickness = parameters.hasOwnProperty("borderThickness") ? parameters["borderThickness"] : 4;
        var borderColor = parameters.hasOwnProperty("borderColor") ?parameters["borderColor"] : { r:0, g:0, b:0, a:1.0 };
        var backgroundColor = parameters.hasOwnProperty("backgroundColor") ?parameters["backgroundColor"] : { r:255, g:255, b:255, a:1.0 };
        var textColor = parameters.hasOwnProperty("textColor") ?parameters["textColor"] : { r:0, g:0, b:0, a:1.0 };

        var canvas = document.createElement('canvas');
        var context = canvas.getContext('2d');
        context.font = "Bold " + fontsize + "px " + fontface;
        var metrics = context.measureText( message );
        var textWidth = metrics.width;

        context.fillStyle   = "rgba(" + backgroundColor.r + "," + backgroundColor.g + "," + backgroundColor.b + "," + backgroundColor.a + ")";
        context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + "," + borderColor.b + "," + borderColor.a + ")";

        context.lineWidth = borderThickness;
        roundRect(context, borderThickness/2, borderThickness/2, (textWidth + borderThickness) * 1.1, fontsize * 1.4 + borderThickness, 8);

        context.fillStyle = "rgba("+textColor.r+", "+textColor.g+", "+textColor.b+", 1.0)";
        context.fillText( message, borderThickness, fontsize + borderThickness);

        var texture = new THREE.Texture(canvas) 
        texture.needsUpdate = true;

        var spriteMaterial = new THREE.SpriteMaterial( { map: texture, useScreenCoordinates: false } );
        var sprite = new THREE.Sprite( spriteMaterial );
    }

    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(); }

    return (
        <>
      <mesh 
      sprite={makeTextSprite('text')}
        {...props}
        ref={mesh}
        className="text"
        >
       
        
      </mesh>
      </>
      
    )
  }




export default Text

如果我可以在我的画布上使用 scene.add,我会使用函数 makeTextSprite 并轻松添加它,但我需要添加为 Text 组件,我该怎么做?

【问题讨论】:

    标签: javascript reactjs three.js react-three-fiber


    【解决方案1】:

    找到了一个临时解决方案,还不错,但是文字有点颗粒感……(下面的版本2看起来更好但是使用了另一个库)

    版本 1

    function Text({ children, position, opacity, color = 'black', fontSize = 35 }) {
    
      
    
      const canvas = useMemo(() => {
        var fontface = "Arial";
        var fontsize = fontSize;
        var borderThickness =  4;
    
        var canvas = document.createElement('canvas');
        var context = canvas.getContext('2d');
        context.textBaseline = 'middle'
        context.font = `bold ${fontSize}px -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif`
    
        var metrics = context.measureText( children );
      var textWidth = metrics.width;
      
        context.lineWidth = borderThickness;
    
        context.fillStyle = color
        context.fillText( children, textWidth - (textWidth*0.8), fontsize);    
        return canvas
      }, [children])
    
    
      return (
        <sprite 
        scale={[5, 3, 3]} position={position}>
          <spriteMaterial attach="material" transparent alphaTest={0.5} >
            <canvasTexture attach="map" image={canvas} />
          </spriteMaterial>
        </sprite>
      )
    }
    
    export default Text
    
    
    <Text opacity={1} position={[8, 2.5, 10]}>Text Content</Text>
    

    第 2 版

    文本看起来更好,保持较低的比例值并通过更改 fontSize 来更改尺寸

    
    import React, { useMemo } from 'react'
    import { SpriteText2D, textAlign } from 'three-text2d'
    
    function Text({ children, position, scale, color = 'white', fontSize = 50 }) {
     
    
      const sprite =  useMemo(() => new SpriteText2D(children,
         { align: textAlign.center,  font: `bold ${fontSize}px Arial`, fillStyle: '#ffffff' , antialias: false }))    
      
    
      return (
        <primitive scale={[0.02,0.02,0.02]} object={sprite} position={position} />
      )
    }
      
    
     
    
    export default Text
    
    
     <Text scale={scale}  opacity={1} position={position}>{children}</Text>
    

    【讨论】:

    • 我发现这个 repo 可以很容易地重写为 react-three-fiber 版本。我绝对受到您的代码的启发,谢谢! github.com/vasturiano/three-spritetext
    • 不客气!我还添加了我目前正在使用另一个库 (three-text2d) 的版本 2。
    猜你喜欢
    • 2022-12-23
    • 1970-01-01
    • 2021-07-11
    • 2021-05-09
    • 2021-06-08
    • 2021-03-15
    • 2021-08-09
    • 2021-08-11
    • 2021-09-09
    相关资源
    最近更新 更多