如何解决React Three Fiber 等效于 scene.add() - 带有 React Three Fiber 的 2D 文本精灵
接下来:three.js 2D Text sprite labels
我找到了如何在three.js上制作2d文本精灵,我现在需要它来反应三个纤维。
我的 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,10]} />
<Text position={[-4,-4,10]} />
<Controls />
</Canvas>
The Box 工作正常,文本我不知道如何在 react 三纤、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,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,(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,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 - r); ctx.lineTo(x,y + r); ctx.quadraticCurveTo(x,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组件,我该怎么做?
解决方法
找到了一个临时解决方案,还不错,但是文字有点颗粒感...(下面的版本 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,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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。