• THREE--demo8(文字)


    效果

    在这里插入图片描述

    源码
    import * as T from 'three'
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
    import { FontLoader } from 'three/examples/jsm/loaders/FontLoader'
    import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'
    import optimerBoldJson from 'three/examples/fonts/optimer_regular.typeface.json'
    import { useEffect, useRef } from 'react'
    
    const Demo7 = () => {
        let scene, camera, renderer, orbitControls, axes, lod
    
        useEffect(() => {
            init()
        }, [])
    
        const ThreeContainer = useRef()
    
        // 场景,作为容器,保存并跟踪所有渲染的物体
        const initScene = () => {
            scene = new T.Scene()
        }
    
        // 相机
        const initCamera = () => {
            // 透视相机,参数:视场,长宽比,近面,远面
            camera = new T.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
            camera.position.z = 200
            camera.lookAt(scene.position)
        }
    
        // 渲染器,计算指定相机角度下,浏览器中scene的样子
        const initRenderer = () => {
            renderer = new T.WebGLRenderer()
            renderer.setClearColor(0xeeeeee)
            renderer.setSize(window.innerWidth, window.innerHeight)
            // 将render的输出挂载到HTML页面框架中的元素上
            ThreeContainer.current.append(renderer.domElement)
        }
    
        // 坐标轴
        const initAxes = () => {
            axes = new T.AxesHelper(20)
            scene.add(axes)
        }
    
        // 轨道控制器
        const initOrbitControls = () => {
            orbitControls = new OrbitControls(camera, renderer.domElement)
        }
    
        // 3D文字
        const add3DFont = () => {
            const fontLoader = new FontLoader()
            // 用 .load 方法报错了
            const font = fontLoader.parse(optimerBoldJson)
            const text = new TextGeometry('Text Demo', {
                // 自带的字体不支持中文,会乱码,需要自己导入中文字体
                font,
                // 字体大小,默认值为100
                size: 10,
                // 挤出文本的厚度,默认值为50
                height: 5,
                // 计算当前几何体的的边界矩形,该操作会更新已有 [param:.boundingBox]
                // 边界矩形不会默认计算,需要调用该接口指定计算边界矩形,否则保持默认值 null
            })
            text.computeBoundingBox()
            // 居中
            const centerOffset = -0.5 * ( text.boundingBox.max.x - text.boundingBox.min.x )
            text.translate(centerOffset, 20, -2.5)
            const material = new T.MeshBasicMaterial({
                color: 0x1890ff
            })
            const mesh = new T.Mesh(text, material)
            mesh.name = 'fontMesh'
            scene.add(mesh)
        }
    
        // 滚动文字
        const addScrollFont = () => {
            const canvas = document.createElement('canvas')
            canvas.width = 100
            canvas.height = 20
            const canvasText = canvas.getContext('2d')
            canvasText.fillStyle = '#ff7875'
            canvasText.fillRect(0, 0, 100, 20)
            canvasText.beginPath()
            canvasText.translate(50, 10)
            canvasText.fillStyle = '#fff'
            canvasText.font = 'bold 10px 宋体'
            canvasText.textBaseline = 'middle'
            canvasText.textAlign = 'center'
            canvasText.fillText('Canvas Text Demo', 0, 0)
    
            const boxGeometry = new T.BoxGeometry(100, 20, 5)
            const canvasTexture = new T.CanvasTexture(canvas)
            // RepeatWrapping 纹理将简单地重复到无穷大
            canvasTexture.wrapS = T.RepeatWrapping
            const material = new T.MeshBasicMaterial({
                map: canvasTexture
            })
            const mesh = new T.Mesh(boxGeometry, material)
            mesh.name = 'canvasMesh'
            scene.add(mesh)
        }
    
        // 渲染场景
        const renderScene = () => {
            scene.traverse(e => {
                if(e.name == 'fontMesh') {
                    e.rotation.y += 0.01
                } else if(e.name == 'canvasMesh') {
                    e.material.map.offset.x += 0.005
                }
            })
            requestAnimationFrame(renderScene)
            renderer.render(scene, camera)
        }
    
        const resize = () => {
            window.addEventListener('resize', () => {
                camera.aspect = window.innerWidth / window.innerHeight
                camera.updateProjectionMatrix()
                renderer.setSize(window.innerWidth, window.innerHeight)
            }, false)
        }
    
        // 初始化
        const init = () => {
            initScene()
            initCamera()
            initRenderer()
            initOrbitControls()
            initAxes()
            add3DFont()
            addScrollFont()
            renderScene()
            resize()
        }
    
        return (
            
    ) } export default Demo7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
  • 相关阅读:
    第15章_锁: MySQL并发访问相同记录以及从数据操作的类型划分锁(读锁、写锁)
    用户端APP自动化测试_L2
    mindspore.dataset的map问题
    AWTK 支持可独立安装的小应用程序 (applet)
    机器人控制算法简要概述
    Mysql数据库常用表结构操作语句
    idea Transparent-native-to-ascii 是否需要勾选?
    常用python包环境命令总结
    文本生成图像工作简述--概念介绍和技术梳理
    Unity中URP实现水体(水下的扭曲)
  • 原文地址:https://blog.csdn.net/weixin_43794073/article/details/126705435