WEB 3D技术 three.js通过光线投射 完成几何体与外界的事件交互

news2025/1/4 15:10:10

本文 我们来说 光线投射
在这里插入图片描述
光线投射技术是用于3维空间场景中的交互事件

我们先编写代码如下

import './style.css'
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";



const scene = new THREE.Scene();
const sphere1 =new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color: 0x00FF00
    })
)
sphere1.position.x = -2;
scene.add(sphere1);

const sphere2 = new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color: 0x0000FF
    })
)
scene.add(sphere2);

const sphere3 = new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color:  0xFFE0FF
    })
)
sphere3.position.x = 2;
scene.add(sphere3);

//创建相机
const camera = new THREE.PerspectiveCamera(
    45, //视角 视角越大  能看到的范围就越大
    window.innerWidth / window.innerHeight,//相机的宽高比  一般和画布一样大最好
    0.1,  //近平面  相机能看到最近的距离
    1000  //远平面  相机能看到最远的距离
);

//c创建一个canvas容器  并追加到 body上
const renderer = new THREE.WebGLRenderer(0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//设置相机位置   这里 我们设置Z轴  大家可以试试  S Y 和 Z  都是可以的
camera.position.z = 5;
//设置相机默认看向哪里   三个 0  代表 默认看向原点
camera.lookAt(0, 0, 0);
//将内容渲染到元素上
renderer.render(scene, camera);
const controls = new OrbitControls(camera, renderer.domElement);

function animate() {
    controls.update();
    requestAnimationFrame(animate);
    /*cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;*/
    renderer.render(scene, camera);
}
animate();

这里 我们声明了三个圆形
运行结果如下
在这里插入图片描述
首先 我们加入 这样的代码

const raycaster = new THREE.Raycaster();
//创建鼠标向量 获取当前鼠标点击位置
const mouse = new THREE.Vector2();
window.addEventListener("click",(event) =>{
    
})

首先 我们定义出 一个射线Raycaster
然后 用Vector2 鼠标点击位置
然后 用window 监听窗口的点击事件

其实 click 的 event 就能拿到点击位置

window.addEventListener("click",(event) =>{
    console.log(event.clientX,event.clientY);
})

获取 x y轴位置
此时 我们点击
控制台就会输出事件触发的坐标
在这里插入图片描述
然后 我们编写代码如下

import './style.css'
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";


//创建相机
const camera = new THREE.PerspectiveCamera(
    45, //视角 视角越大  能看到的范围就越大
    window.innerWidth / window.innerHeight,//相机的宽高比  一般和画布一样大最好
    0.1,  //近平面  相机能看到最近的距离
    1000  //远平面  相机能看到最远的距离
);
const scene = new THREE.Scene();
const sphere1 =new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color: 0x00FF00
    })
)
sphere1.position.x = -2;
scene.add(sphere1);

const sphere2 = new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color: 0x0000FF
    })
)
scene.add(sphere2);

const sphere3 = new THREE .Mesh(
    new THREE.SphereGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
        color:  0xFFE0FF
    })
)
sphere3.position.x = 2;
scene.add(sphere3);
//创建射线
const raycaster = new THREE.Raycaster();
//创建鼠标向量 获取当前鼠标点击位置
const mouse = new THREE.Vector2();
window.addEventListener("click",(event) =>{
    console.log(event.clientX,event.clientY);
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -((event.clientY / window.innerHeight) * 2 - 1);

    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
    console.log(intersects);
})

//c创建一个canvas容器  并追加到 body上
const renderer = new THREE.WebGLRenderer(0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//设置相机位置   这里 我们设置Z轴  大家可以试试  S Y 和 Z  都是可以的
camera.position.z = 5;
//设置相机默认看向哪里   三个 0  代表 默认看向原点
camera.lookAt(0, 0, 0);
//将内容渲染到元素上
renderer.render(scene, camera);
const controls = new OrbitControls(camera, renderer.domElement);

function animate() {
    controls.update();
    requestAnimationFrame(animate);
    /*cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;*/
    renderer.render(scene, camera);
}
animate();

主要是 我们点击事件
先算出 鼠标当前相对坐标
然后 调用射线对象的 setFromCamera 他需要两个参数
第一个 Vector2 对象 x y轴用来确认触发事件的位置
第二个 是我们全局创建的相机对象 我们这里叫 camera
然后 raycaster.intersectObjects 绑定元素 帮助我们获取到被接触的几何体 这里 如果鼠标点击的位置 包括 我们传进去的三个几何体 就会被收集起来

我们运行代码 然后没有物体的位置
收集的数组就是个空的
在这里插入图片描述
我们点击其中一个几何体
控制台就输出了它收集到的内容
在这里插入图片描述
我们将点击事件的代码改成这样

window.addEventListener("click",(event) =>{
    console.log(event.clientX,event.clientY);
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -((event.clientY / window.innerHeight) * 2 - 1);

    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
    if (intersects.length > 0) {
        intersects[0].object.material.color.set(0xff0000);
    }
})

这里 我们看他收集的 intersects 如果长多超过 0 说明是拿到东西了的
我们将被收集的 0下标物体 材质对象中的 color 颜色字段 set成0xff0000 红色

运行代码 我们点击圆形 即可变为红色了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1350286.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis Cluster集群模式学习

Redis Cluster集群模式 Redis哨兵模式:https://blog.csdn.net/liwenyang1992/article/details/133956200 Redis Cluster集群模式示意图: Cluster模式是Redis3.0开始推出采用无中心结构,每个节点保存数据和整个集群状态,每个节点都…

【python】Python 3.11不支持Tix库

Tix库主要用于扩展Tkinter,但是Python 3.11 Tkinter已经不再支持Tix库。Tix模块提供了一些额外的部件和功能,但现在这些功能已经整合到了Tkinter库中。 一、如果在Python 3.11中想要使用Tix库,但发现它不再被内置支持,可以尝试以…

使用Wireshark进行网络流量分析

目录 Wireshark是什么? 数据包筛选 筛选指定ip 使用逻辑运算符筛选 HTTP模式过滤 端口筛选 协议筛选 包长度筛选 数据包搜索 数据流分析 数据包导出 Wireshark是什么? 通过Wireshark,我们可以捕获和分析网络数据包,查看…

ARM CCA机密计算硬件架构之内存管理

实施了TrustZone安全扩展的Arm A-profile处理器呈现两个物理地址空间(PAS): 非安全物理地址空间安全物理地址空间Realm管理扩展增加了两个PAS: Realm物理地址空间Root物理地址空间下图显示了这些物理地址空间以及如何在工作系统中实施这些空间: 正如表格所示,根状态能够访…

2024,启动(回顾我的2023)

零.前言 打开博客想写个年度总结,发现已经半年没有更新文章了,排名从几千掉到了几万,不过数据量还是不错的。 时间过得可真快,2023年是充满动荡的一年,上半年gpt横空出世,下半年各种翻车暴雷吃瓜吃到嘴软…

计算机毕业设计选题分享-Springboot在线问诊系统00211(赠送源码数据库)JAVA、PHP,node.js,C++、python,大屏数据可视化等

Springboot在线问诊系统 摘 要 针对医院门诊等问题,对在线问诊进行研究分析,然后开发设计出在线问诊系统以解决问题。在线问诊系统主要功能模块包括首页、轮播图管理、公告信息管理、资源管理、系统用户管理(管理员、患者用户、医生用户&…

golang并发编程-channel

在golang 并发编程里,经常会听到一句话:不要通过共享内存进行通信,通过通信来共享内存。下面我们会介绍下channel, 通过源码的方式去了解channel是怎么工作的。 基本结构 流程图 代码解读 type hchan struct {qcount uint // …

【银行测试】超细支付功能测试+测试点总结分析(详全)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、支付功能怎么测…

从零开始:使用 BIND 构建和管理您的 DNS 服务器

1 前言 在这篇文章中,我将详细介绍如何使用 BIND(Berkeley Internet Name Domain)软件包中的 named 程序来配置和管理一个基本的 DNS 服务器。 从安装 BIND 开始,到设置 DNS 区域文件,再到运行和测试您的服务器&#x…

ROS学习记录:ROS系统中的激光雷达消息包的数据格式

一、在工作空间中输入source ./devel/setup.bash 二、输入roslaunch wpr_simulation wpb_simple.launch打开机器人仿真环境 三、机器人仿真环境打开成功 四、给机器人围上一圈障碍物 五、再打开一个工作空间终端 六、输入roslaunch wpr_simulation wpb_rviz.launch打开RViz 七、…

Node.js使用jemalloc内存分配器显著减少内存使用

前言 Node.js 默认使用的是 ptmalloc(glibc) 内存分配器,而: 在服务端领域「不会选择默认的 malloc」是一个常识。( 来源 ) ptmalloc 的分配效率较低( 来源 ),对于 长时间、多核 / 多线程 运行…

手机录屏没有声音?让你的录屏有声有色

“有人知道手机录屏怎么录声音吗?今天录制了一个小时的直播视频,后面查看的时候发现没有声音,真的非常崩溃,想问问大家有没有办法,解决这个问题。” 在手机录屏的过程中,有时候我们可能会面临录制视频没有…

第19届楚天春晚在九省通衢大武汉闪亮登场

——中国明星后代女子歌舞团刘亦菲等兼任形象大使 2024年新年伊始,一场以繁荣中国传统文化为主旨的“楚天春晚”全国文旅活动在湖北武汉拉开帷幕!以“文化强省,旅游大省”为神州特色的联合国世界品牌之都,在辞旧迎新的早春来临之…

手机摄影学习

手机摄影学习 基础知识1,成像基本原理2,什么是焦距3,快门(简称s)4,上面功能之间的相互影响5,焦点6,过爆、欠曝7,cmos(感光芯片)、测光、聚焦&…

考研用什么光源比较好?五款好用台灯推荐

人眼对光是非常敏感的,特别是儿童青少年眼睛还在发育的状态来说,光线是至关重要的,于是这次测评就不能马虎,必须要本着专业严谨的态度进行测评,这次测评呢就花了不少钱买下了现在市面上热度很高、或是较有名气的专业款…

贝锐花生壳全新功能:浏览器一键远程访问SSHRDP远程桌面

为了满足特定场景的远程访问需求,如:远程群晖NAS设备、远程SQL Server数据库/MySQL数据库、3389远程桌面(RDP远程桌面)、远程SSH、我的世界游戏联机…… 贝锐花生壳推出了场景映射服务,不仅提供满足相应场景的网络带宽…

机器人活动区域 - 华为OD统一考试

OD统一考试 题解: Java / Python / C++ 题目描述 现有一个机器人,可放置于 M x N 的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差值的绝对值小于等于 1 时机器人可以在网格间移动。 问题: 求机器人可活动的最大范围对应的网格点数目。 说明: 网格…

剑指“CPU飙高”问题

一、什么是cpu飙高? 一般指程序运行时cpu占用率过高   linux系统中,我们使用top命令,会看到正在运行进程的cpu使用率等,同时在最上面也会看到总的cpu使用率,当总的cpu使用率过高,如果有运维监控平台&…

听GPT 讲Rust源代码--library/portable-simd

File: rust/library/portable-simd/crates/core_simd/examples/spectral_norm.rs spectral_norm.rs是一个示例程序,它展示了如何使用Portable SIMD库中的SIMD(Single Instruction Multiple Data)功能来实现频谱规范化算法。该示例程序是Rust源…

严格的老师对学生的好处

从踏入学校的大门开始,我们便与老师结下了不解之缘。他们不仅是传授知识的导师,更是陪伴我们成长的良师益友。其中,那些对学生要求严格的老师,更是让我们受益匪浅。他们以严谨的教育态度,为学生点亮了前行的路。 塑造良…