three.js给模型添加标签三种方式对比(矩形平面,精灵图,CSS2DObject)

three.js给模型添加标签三种方式对比(矩形平面,精灵图,CSS2DObject)

vue3实现,代码如下

代码

javascript 复制代码
<template>
  <div class="app">
    <div ref="canvesRef" class="canvas-wrap"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";

const canvesRef = ref(null);
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;

// 场景
const scene = new THREE.Scene();
// 模型
for (let i = 0; i < 3; i++) {
  const geometry = new THREE.BoxGeometry(40, 40, 40);
  const material = new THREE.MeshBasicMaterial({
    color: 0x00ffff,
  });
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(i * 70, 0, 0);
  scene.add(mesh);
}
// 相机
const camera = new THREE.PerspectiveCamera(
  75,
  canvasWidth / canvasHeight,
  0.1,
  3000
);
camera.position.set(200, 200, 200);
camera.lookAt(0, 0, 0);

// 坐标辅助对象
const axesHelper = new THREE.AxesHelper(200);
scene.add(axesHelper);

// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(canvasWidth, canvasHeight);

// 1.使用矩形平面实现标签
const planeGeometry = new THREE.PlaneGeometry(40, 20);
const texLoader = new THREE.TextureLoader();
const tex = texLoader.load("../src/assets/img/icon.png");
const planeMaterial = new THREE.MeshBasicMaterial({
  // 设置纹理贴图:Texture对象作为材质map属性的属性值
  map: tex, //map表示材质的颜色贴图属性
  side: THREE.DoubleSide,
});
const meshP = new THREE.Mesh(planeGeometry, planeMaterial);
meshP.position.set(0, 60, 0);
scene.add(meshP);
// 2.使用精灵图
const spriteMaterial = new THREE.SpriteMaterial({
  color: 0x00ff00, //设置颜色
  map: tex,
});
const sprite = new THREE.Sprite(spriteMaterial);
sprite.position.set(70, 60, 0);
sprite.scale.set(40, 20, 1);
scene.add(sprite);

// 3.CSS2DObject
const textDiv = document.createElement("div");
textDiv.className = "label";
textDiv.textContent = "Earth";
textDiv.style.backgroundColor = "transparent";
textDiv.style.color = "#fff";

const textLabel = new CSS2DObject(textDiv);
textLabel.position.set(140, 60, 0);
scene.add(textLabel);


const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = "absolute";
labelRenderer.domElement.style.top = "0px";
console.log(labelRenderer.domElement);
document.body.appendChild(labelRenderer.domElement);

// 动画渲染循环
function animate() {
  renderer.render(scene, camera);
  labelRenderer.render(scene, camera);

  requestAnimationFrame(animate);
}
animate();
// 相机轨道控制器
const cameraControls = new OrbitControls(camera, labelRenderer.domElement);
cameraControls.target.set(0, 0, 0); // 与相机的lookat保持一致
cameraControls.maxPolarAngle = Math.PI / 2; // 相机不能进入地下

onMounted(() => {
  canvesRef.value.appendChild(renderer.domElement);
});
</script>

<style lang="scss" scoped>
.app {
  position: relative;
}
</style>

效果如下

  1. 正前方观察

  2. 相机位观察(右上角)

  3. 右后方观察

  4. 缩小

总结

  1. 矩形平面方向不会改变,另外两种一直面向屏幕
  2. CSS2模型对象CSS2DObject不会缩小
  3. Spirte没有几何体,需要通过sprite.scale定义矩形精灵的长和宽。
相关推荐
C+ 安口木15 分钟前
纯前端实现图文识别 OCR
前端·javascript·ocr
勇敢*牛牛41 分钟前
SVG 与 Canvas 技术调研对比
javascript
NoneCoder42 分钟前
正则表达式与文本处理的艺术
前端·javascript·面试·正则表达式
海盐泡泡龟3 小时前
Javascript本地存储的方式有哪些?区别及应用场景?(含Deep Seek讲解)
开发语言·javascript·ecmascript
计算机学姐5 小时前
基于SpringBoot的小型民营加油站管理系统
java·vue.js·spring boot·后端·mysql·spring·tomcat
Elastic 中国社区官方博客5 小时前
JavaScript 中使用 Elasticsearch 的正确方式,第一部分
大数据·开发语言·javascript·数据库·elasticsearch·搜索引擎·全文检索
万物得其道者成5 小时前
从零开始创建一个 Next.js 项目并实现一个 TodoList 示例
开发语言·javascript·ecmascript
sunbyte6 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Expanding Cards (展开式卡片)
javascript·vue.js·ecmascript
肠胃炎6 小时前
React Contxt详解
javascript·react.js·ecmascript
xx24066 小时前
React Native简介
javascript·react native·react.js