如何在 Three.js 场景中创建可点击展开的标签

news/2024/9/28 22:18:56/

在这里插入图片描述

在复杂的可视化场景中,经常需要为 3D 对象添加可交互的标签,以便用户点击时可以查看详细信息。这篇文章将通过一个简单的案例展示,如何在 Three.js 中为对象创建可点击的标签,点击标签可以展开详细信息,再次点击可以关闭这些信息。

实现思路
  1. 创建护罩对象:我们在 Three.js 中生成护罩(类似于 3D 球体),这些护罩将承载标签。
  2. 创建 2D 标签:使用 Three.js 的 CSS2DRenderer 创建 HTML 标签,并附加到护罩对象上。
  3. 实现点击交互:点击标签时,显示更多信息,再次点击时隐藏这些信息。
第一步:创建基本的 Three.js 场景

我们首先需要在项目中创建一个基本的 Three.js 场景,并在其中生成几个护罩对象。以下代码展示了如何设置 Three.js 场景和护罩:

javascript">import * as THREE from 'three'; 
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';// 创建基本的 Three.js 场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(labelRenderer.domElement);// 添加灯光
const ambientLight = new THREE.AmbientLight(0x404040, 2); 
scene.add(ambientLight);// 创建护罩对象
const geometry = new THREE.SphereGeometry(1.5, 32, 32);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const shield = new THREE.Mesh(geometry, material);
scene.add(shield);

这个代码片段中,我们创建了一个基础的 Three.js 场景,设置了相机、灯光,并添加了一个简单的护罩对象(一个球体)。还初始化了一个 CSS2DRenderer 用于接下来渲染 HTML 标签。

第二步:为护罩添加 2D 标签

接下来,我们将使用 CSS2DRenderer 来为护罩添加一个标签。这个标签将包含护罩的名称,并且初始状态下显示基本信息,更多信息隐藏。

javascript">// 创建标签元素
const div = document.createElement('div');
div.className = 'label';
div.textContent = 'Shield 1';
div.style.fontSize = '14px';
div.style.color = 'white';
div.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
div.style.padding = '5px';
div.style.borderRadius = '5px';
div.style.cursor = 'pointer';// 创建隐藏的详细信息元素
const moreContent = document.createElement('div');
moreContent.className = 'more-content';
moreContent.style.display = 'none';
moreContent.textContent = '更多关于 Shield 1 的内容...';
moreContent.style.marginTop = '5px';
moreContent.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
moreContent.style.color = 'black';
moreContent.style.padding = '10px';
moreContent.style.borderRadius = '5px';// 将详细信息嵌入标签中
div.appendChild(moreContent);// 为护罩添加点击事件,控制显示和隐藏详细信息
div.addEventListener('click', () => {moreContent.style.display = moreContent.style.display === 'none' ? 'block' : 'none';
});// 创建 CSS2DObject,将标签附加到护罩上
const label = new CSS2DObject(div);
label.position.set(0, 2, 0); // 标签位置在护罩上方
shield.add(label);

在这段代码中,我们:

  1. 创建了 HTML 标签,并设置了样式,包括护罩名称和背景颜色。
  2. 创建了详细信息的部分,初始状态下隐藏。
  3. 通过点击事件实现了点击标签时展开或收起详细信息。
第三步:渲染场景并添加交互

最后,我们将把标签添加到 Three.js 的渲染循环中,同时确保标签随 3D 场景中的对象移动。

javascript">// 渲染循环
function animate() {requestAnimationFrame(animate);renderer.render(scene, camera);labelRenderer.render(scene, camera); // 渲染标签
}
animate();

现在,运行这个代码时,会看到一个带有标签的护罩对象。点击标签时,会显示详细信息,再次点击时会隐藏详细信息。

第四步:为什么标签没有显示在边缘?

生成的标签附加在护罩的顶部,护罩的分布范围可能会限制标签在屏幕中的可见位置。在我们的项目中,护罩是以屏幕中心为基准进行分布,因此没有分布到屏幕边缘。为了将护罩分布得更广,可以调整护罩的位置逻辑,确保护罩覆盖到屏幕的边缘区域。

总结

在这篇文章中,我们展示了如何使用 Three.js 的 CSS2DRenderer 为 3D 场景中的对象添加 2D 标签,并实现点击显示或隐藏详细信息的交互效果。这个功能可以应用于各种 3D 数据可视化场景中,为用户提供直观的交互体验。

ps:最近的项目使用three.js的地方很多,且拓展了很多功能,我会将一个个的功能点拆分出来。因为之前查找相关博客发现很多都是整个一起的,对于只想要其中一部分而言会增加很多不必要的时间成本,所以我会将功能点拆解出来。想了解更多关于three.js的文章可以看我的three专栏

跳转连接:【Three.js】实现护罩(防御罩、金钟罩、护盾)效果


http://www.ppmy.cn/news/1531356.html

相关文章

用户态缓存:环形缓冲区(Ring Buffer)

目录 环形缓冲区(Ring Buffer)简介 为什么选择环形缓冲区? 代码解析 1. 头文件与类型定义 1.1 头文件保护符 1.2 包含必要的标准库 1.3 类型定义 2. 环形缓冲区结构体 2.1 结构体成员解释 3. 辅助宏与内联函数 3.1 min 宏 3.2 is…

企微SOP:构建标准化运营流程,驱动企业高效增长

在当今竞争激烈的市场环境中,企业微信的(简称“企微”)运用已成为企业与客户沟通、服务及营销的重要渠道。为了确保企微运营的高效性、一致性和可复制性,企业亟需建立一套标准化的运营流程(Standard Operating Procedu…

MyBatis 中#{} 和 ${} 的区别

在 MyBatis 中,#{} 和 ${} 都是用来在 SQL 语句中插入动态参数的,但是它们之间存在重要的区别: #{} 的特点: 预编译处理:当使用 #{} 时,MyBatis 会将 SQL 语句中的参数占位符转换为预编译语句 (PreparedSt…

STL05——手写一个简单版本的红黑树(500+行代码)

STL05——手写一个简单版本的红黑树 题目描述 在STL中,红黑树是一个重要的底层数据结构,本题需要设计一个 RedBlackTree 类,实现如下功能: 1、基础功能 构造函数:初始化 RedBlackTree 实例析构函数:清理…

Packet Tracer - IPv4 ACL 的实施挑战(完美解析)

目标 在路由器上配置命名的标准ACL。 在路由器上配置命名的扩展ACL。 在路由器上配置扩展ACL来满足特定的 通信需求。 配置ACL来控制对网络设备终端线路的 访问。 在适当的路由器接口上,在适当的方向上 配置ACL。…

JMeter源码解析之JMeter命令行新增命令

JMeter源码解析之JMeter命令行新增命令 需求描述 需要新增一条命令,能够在JMeter命令行中能够展示输入对应的JMeter命令,能够展示对应的命令信息 查看命令效果如下: apache-jmeter-5.1\bin>jmeter --? Copyright © 1999-2024 The …

Efficient DETR: Improving End-to-End Object Detector with Dense Prior

原文链接 [2104.01318] Efficient DETR: Improving End-to-End Object Detector with Dense Prior (arxiv.org)https://arxiv.org/abs/2104.01318 原文笔记 What 1、一种针对DETR的objectquery初始化的方法 2、针对Deformable DETR进行改进,改进之后的模型具有…

计算机网络发展

目录 一、计算机网络的起源 1.1 ARPANET的诞生 1.2 TCP/IP协议的提出 二、互联网的兴起与普及 2.1 DNS系统的建立 2.2 万维网的诞生 2.3 互联网的商业化 三、宽带和无线网络的发展 3.1 宽带网络的普及 3.2 无线网络与移动互联网 四、互联网的未来趋势 4.1 5G与物联网…