Three.js 精灵文字教程
精灵文字 ·Sprite Text· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么OrbitControls 相机轨道交互Canvas 动态纹理贴图requestAnimationFrame渲染循环与resize自适应效果说明本案例演示精灵文字效果用 Canvas 2D 绘制内容并实时映射为 Three.js 纹理核心用到 OrbitControls、Canvas。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念OrbitControls轨道旋转缩放开enableDamping时每帧需controls.update()。实现步骤搭建 Scene / Camera / Renderer 与 OrbitControlsrAF 循环中 update 并 render代码要点import * as THREE from threeimport { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)camera.position.set(0, 10, 10)const renderer new THREE.WebGLRenderer()renderer.setSize(box.clientWidth, box.clientHeight)box.appendChild(renderer.domElement)new OrbitControls(camera, renderer.domElement)scene.add(new THREE.AmbientLight(0xffffff, 3), new THREE.AxesHelper(1000))animate()function animate() {requestAnimationFrame(animate)renderer.render(scene, camera)}window.onresize () {renderer.setSize(box.clientWidth, box.clientHeight)camera.aspect box.clientWidth / box.clientHeightcamera.updateProjectionMatrix()}const citys await fetch(https://z2586300277.github.io/three-editor/dist/files/other/city.json).then(res res.json()) // 获取城市数据const updateCanvasText createCanvasText({ dpr: 1.4 }) // 创建canvasconst getColor () # Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, 0) // 随机颜色for (const key in citys) {const canvas updateCanvasText({ text: key, color: getColor() })const texture new THREE.TextureLoader().load(canvas.toDataURL())const material new THREE.SpriteMaterial({ map: texture })const sprite new THREE.Sprite(material)sprite.scale.set(canvas.width / canvas.height, 1, 1)// 设置随机位置 sprite.position.set( Math.random() * 20 - 10, Math.random() * 20 - 10, Math.random() * 20 - 10 )scene.add(sprite)}// 创建canvas文字方法 function createCanvasText(params) {const defaultParams { dpr: 1, maxWidth: 100, fontSize: 20, color: white, fontFamily: serif, align: center, border: false, ...params } // 默认参数const { dpr, border, maxWidth, fontSize, align } defaultParamsconst devicePixelRatio window.devicePixelRatio * dpr// 准备 cnvas const canvas document.createElement(canvas)canvas.width maxWidth * devicePixelRatiocanvas.height fontSize * devicePixelRatio// 获取 2d 上下文 const ctx canvas.getContext(2d)ctx.imageSmoothingQuality highctx.scale(devicePixelRatio, devicePixelRatio)// 创建边框 function createBorder() {ctx.strokeStyle #fff// 创建宽度为10px的边框 ctx.lineWidth 1 * devicePixelRatio;ctx.strokeRect(ctx.lineWidth / 2,ctx.lineWidth / 2,canvas.width / devicePixelRatio - ctx.lineWidth,canvas.height / devicePixelRatio - ctx.lineWidth)}// 创建文字 const createText ({ text, color, fontSize, fontFamily }) {// 参数设定 ctx.fillStyle color || defaultParams.colorctx.font fontSize || defaultParams.fontSize px fontFamily || defaultParams.fontFamily// 文本长度计算 let textMaxNum 0let totalWidth 0for (let i 0; i text.length; i) {const metrics ctx.measureText(text[i])totalWidth metrics.width;if (totalWidth maxWidth) breaktextMaxNum}text text.slice(0, textMaxNum)// 文字 绘制 const metrics ctx.measureText(text) // 文本尺寸const actualHeight metrics.actualBoundingBoxAscent metrics.actualBoundingBoxDescent // 实际文字高度const textFillHeight (canvas.height / devicePixelRatio - actualHeight) / 2 metrics.actualBoundingBoxAscentlet textLeftOffset 0if (align center) textLeftOffset (canvas.width / devicePixelRatio - metrics.width) / 2ctx.fillText(text, textLeftOffset, textFillHeight, canvas.width / devicePixelRatio)}return (parameters) {ctx.clearRect(0, 0, canvas.width, canvas.height) // 清空 canvas 文字if (border) createBorder() // 创建边框createText(parameters) // 创建文字return canvas}}完整源码GitHub小结本文提供精灵文字完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库