本文介绍了如何在 3D 球体周围环绕文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在巴比伦或 Threejs 中将文本环绕在球体周围的方法.我对改变 javascript 技术持开放态度

I'm looking for a way to wrap text around sphere in babylon or threejs. And i'm open-minded for changing javascript technology

推荐答案

我会看看 生成文本的示例.然后我会分别生成每个字母,记录它们各自的宽度,并使用它们来计算我想要显示的整个字符串的总宽度

I would look at an example of generating text. I’d then generate each letter separately recording their individual widths and use those to compute the total width across the string I want to display

然后我可以将每个网格作为 Object3D 的父对象,并将 Object3D 的旋转 y 设置为

I could then parent each mesh to an Object3D and set that Object3D’s rotation y to

widthSoFar = 0;
for each letter
   obj3d.rotation.y = widthSoFar / totalWidth * Math.PI * 2;
   widthSoFar += widthOfCurrentLetter;

并将字母的 position.z 设置为某个半径,这将使字母围绕一个圆圈.

And set the letter’s position.z to some radius which would put the letters around a circle.

什么半径?

circumference = 2 * PI * radius

所以

radius = circumference / (2 * PI)

我们知道我们需要的周长,它是字符串的总宽度.

We know the circumference we need, it’s the totalWidth of the string.

您可能会发现本教程有助于理解如何使用场景图节点(如 Object3D 节点)来组织场景以满足您的需求.

You might find this tutorial helpful in understanding how to use scene graph nodes (like the Object3D node) to organize a scene to meet your needs.

'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 40;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 1000;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 70;

  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  function addLight(...pos) {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(...pos);
    scene.add(light);
  }
  addLight(-4, 4, 4);
  addLight(5, -4, 4);

  const lettersTilt = new THREE.Object3D();
  scene.add(lettersTilt);
  lettersTilt.rotation.set(
     THREE.Math.degToRad(-15),
     0,
     THREE.Math.degToRad(-15));
  const lettersBase = new THREE.Object3D();
  lettersTilt.add(lettersBase);
  {
    const letterMaterial = new THREE.MeshPhongMaterial({
      color: 'red',
    });
    const loader = new THREE.FontLoader();
    loader.load('https://threejsfundamentals.org/threejs/resources/threejs/fonts/helvetiker_regular.typeface.json', (font) => {
      const spaceSize = 1.0;
      let totalWidth = 0;
      let maxHeight = 0;
      const letterGeometries = {
        ' ': { width: spaceSize, height: 0 }, // prepopulate space ' '
      };
      const size = new THREE.Vector3();
      const str = 'threejs fundamentals ';
      const letterInfos = str.split('').map((letter, ndx) => {
        if (!letterGeometries[letter]) {
          const geometry = new THREE.TextBufferGeometry(letter, {
            font: font,
            size: 3.0,
            height: .2,
            curveSegments: 12,
            bevelEnabled: true,
            bevelThickness: 0.5,
            bevelSize: .3,
            bevelSegments: 5,
          });
          geometry.computeBoundingBox();
          geometry.boundingBox.getSize(size);
          letterGeometries[letter] = {
            geometry,
            width: size.x / 2, // no idea why size.x is double size
            height: size.y,
          };
        }
        const {geometry, width, height} = letterGeometries[letter];
        const mesh = geometry
            ? new THREE.Mesh(geometry, letterMaterial)
            : null;
        totalWidth += width;
        maxHeight = Math.max(maxHeight, height);
        return {
          mesh,
          width,
        };
      });
      let t = 0;
      const radius = totalWidth / Math.PI;
      for (const {mesh, width} of letterInfos) {
        if (mesh) {
          const offset = new THREE.Object3D();
          lettersBase.add(offset);
          offset.add(mesh);
          offset.rotation.y = t / totalWidth * Math.PI * 2;
          mesh.position.z = radius;
          mesh.position.y = -maxHeight / 2;
        }
        t += width;
      }
      {
        const geo = new THREE.SphereBufferGeometry(radius - 1, 32, 24);
        const mat = new THREE.MeshPhongMaterial({
         color: 'cyan',
        });
        const mesh = new THREE.Mesh(geo, mat);
        scene.add(mesh);
      }
      camera.position.z = radius * 3;
    });
  }

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    lettersBase.rotation.y = time * -0.5;

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
body {
  margin: 0;
}
#c {
  width: 100vw;
  height: 100vh;
  display: block;
}
<canvas id="c"></canvas>
  <script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>

这篇关于如何在 3D 球体周围环绕文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 12:18