Javascript React三根光纤等效于场景。添加()-2D文本精灵和React三根光纤

Javascript React三根光纤等效于场景。添加()-2D文本精灵和React三根光纤,javascript,reactjs,three.js,react-three-fiber,Javascript,Reactjs,Three.js,React Three Fiber,在此之后: 我找到了如何在three.js上创建2d文本精灵,我现在需要它来制作react three fiber 我的index.js上有这个: <Canvas gl={{}} orthographic camera={{zoom: 20, position: [28, 22, 26]}} color={'#FF3333'} > <ambientLight />

在此之后:

我找到了如何在three.js上创建2d文本精灵,我现在需要它来制作react three fiber

我的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>

这个盒子工作得很好,文本我不知道如何在react-three-fiber,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


功能文本(道具){
//此参考将使我们能够直接访问网格
const mesh=useRef()
函数makeTextSprite(消息、参数)
{
如果(参数===未定义)参数={};
var fontface=parameters.hasOwnProperty(“fontface”)?参数[“fontface”]:“Arial”;
var fontsize=parameters.hasOwnProperty(“fontsize”)?参数[“fontsize”]:18;
var borderThickness=parameters.hasOwnProperty(“borderThickness”)?参数[“borderThickness”]:4;
var borderColor=parameters.hasOwnProperty(“borderColor”)?参数[“borderColor”]:{r:0,g:0,b:0,a:1.0};
var backgroundColor=parameters.hasOwnProperty(“backgroundColor”)?参数[“backgroundColor]:{r:255,g:255,b:255,a:1.0};
var textColor=parameters.hasOwnProperty(“textColor”)?参数[“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(消息);
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=边框厚度;
roundRect(上下文,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(消息、边框厚度、字体大小+边框厚度);
var纹理=新的三点纹理(画布)
texture.needsUpdate=true;
var spriteMaterial=new THREE.spriteMaterial({map:texture,useScreenCoordinates:false});
变量sprite=新的三个sprite(spriteMaterial);
}
函数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,x+w-r,y+h);ctx.lineTo(x+r,y+h);ctx.quadraticCurveTo(x,y+h,y,x+r);ctx.quadraticCurveTo(x,y,x+r,y);ctx.closePath();ctx.fill();ctx.stroke();}
返回(
)
}
导出默认文本

如果我可以在画布上使用scene.add,我只需要使用函数makeTextSprite并轻松添加它,但我需要将其添加为文本组件,如何才能做到这一点?

找到了一个临时解决方案,没有那么糟糕,但文本有点粗糙。。。(下面的版本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

函数文本({children,position,opacity,color='black',fontSize=35}){
const canvas=useMoom(()=>{
var fontface=“Arial”;
var fontsize=fontsize;
var边界厚度=4;
var canvas=document.createElement('canvas');
var context=canvas.getContext('2d');
context.textb基线='middle'
context.font=`bold${fontSize}px-苹果系统、BlinkMacSystemFont、avenir next、avenir、helvetica neue、helvetica、ubuntu、roboto、noto、segoe ui、arial、无衬线字体`
var metrics=context.measureText(子对象);
var textWidth=metrics.width;
context.lineWidth=边框厚度;
context.fillStyle=颜色
context.fillText(子项,textWidth-(textWidth*0.8),fontsize);
返回画布
}[儿童])
返回(
)
}
导出默认文本
文本内容
第2版

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


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


从“React”导入React,{useMemo}
从'three-text2d'导入{SpriteText2D,textAlign}
函数文本({子级,位置,比例,颜色='white',fontSize=50}){
const sprite=useMemo(()=>new SpriteText2D(子级、,
{align:textAlign.center,字体:`bold${fontSize}px Arial`,填充样式:'#ffffff',反别名:false})
返回(
)
}
导出默认文本
{children}

我发现该回购协议可以很容易地重写,以应对三纤版本。我完全被你的代码所启发,谢谢!不客气!我还添加了版本2,我目前正在使用另一个库(三文本2D)。

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>