首页 > 其他分享 >Threejs之光线投射Raycaster交互

Threejs之光线投射Raycaster交互

时间:2024-09-11 21:49:08浏览次数:14  
标签:Raycaster Threejs const THREE window camera renderer 投射 new

这里写目录标题

前言

基于上篇文章Threejs之光线投射Raycaster我们知道了光线投射的基础用法,在本届我们将使用光线投射进行鼠标交互事件

一、前置准备

1.1 代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <script type="module">
        // 倒入轨道控制器
        import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
        import * as THREE from "three";
        // 创建场景
        const scene = new THREE.Scene();

        // 创建相机
        const camera = new THREE.PerspectiveCamera( // 透视相机
            45, // 视角 角度数
            window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
            0.1, // 近平面(相机最近能看到物体)
            1000, // 远平面(相机最远能看到物体)
        );
        camera.position.set(0, 2, 20);
        // camera.lookAt(0, 0, 0);

        // 创建渲染器
        const renderer = new THREE.WebGLRenderer({
            antialias: true, // 抗锯齿
        });
        // 设置渲染器宽高
        renderer.setSize(window.innerWidth, window.innerHeight)
        // renderer(渲染器)的dom元素添加到我们的HTML文档中
        document.body.appendChild(renderer.domElement)

        // 开启坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);

		const geometry = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
		const geometry1 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
		const geometry2 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
        geometry1.position.x = 3;
        geometry2.position.x = -3;
		scene.add(geometry, geometry1, geometry2);

        // 控制器
        const control = new OrbitControls(camera, renderer.domElement);
        // 开启阻尼惯性,默认值为0.05
        control.enableDamping = true;
       
        // 渲染循环动画
        function animate() {
            // 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
            requestAnimationFrame(animate);
          
            // 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
            control.update();
            renderer.render(scene, camera);
        };

        // 执行动画
        animate();
    </script>
</body>
</html>

1.2 效果

在这里插入图片描述
在这里插入图片描述
可以看到我们在场景中放了三个球,并且设置了坐标轴辅助线。


二、添加交互事件

2.1 代码

添加鼠标交互事件,在鼠标点下去的时候我们去发射一束射线,让与之交互的物体做出一些改变,例如改变物体颜色,添加如下代码:

        // 表示2D vector(二维向量)的类
        const mouse = new THREE.Vector2();

        let geometryArr = [geometry, geometry1, geometry2];
        const raycaster = new THREE.Raycaster();

        // 监听鼠标点击事件
        window.addEventListener("mousedown", (event) => {
            // 转换为一个位于二维空间中的点,在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            console.log(mouse.x, mouse.y);
            // 使用一个新的原点和方向来更新射线
            raycaster.setFromCamera(mouse, camera);
            // 每次点击循环设置物体初始颜色,如不设置会导致点击物体后颜色变后不能再变
            for(const geometry of geometryArr) {
                geometry.material.color.set(0xff0000);
            }
            // 相交的物体变色
            const itgeometrys = raycaster.intersectObjects(geometryArr);
            for(const itgeometry of itgeometrys) {
                itgeometry.object.material.color.set(0xcc33f4);
            }
            
        })

2.2 效果

请添加图片描述
可以看到我们已经完成了简单的物体交互。不要小瞧了光线投射,在我们与物体交互中起来很大的作用。


三、完整代码

最后给出本届完整代码,如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <script type="module">
        // 倒入轨道控制器
        import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
        import * as THREE from "three";
        // 创建场景
        const scene = new THREE.Scene();

        // 创建相机
        const camera = new THREE.PerspectiveCamera( // 透视相机
            45, // 视角 角度数
            window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
            0.1, // 近平面(相机最近能看到物体)
            1000, // 远平面(相机最远能看到物体)
        );
        camera.position.set(0, 2, 20);
        // camera.lookAt(0, 0, 0);

        // 创建渲染器
        const renderer = new THREE.WebGLRenderer({
            antialias: true, // 抗锯齿
        });
        // 设置渲染器宽高
        renderer.setSize(window.innerWidth, window.innerHeight)
        // renderer(渲染器)的dom元素添加到我们的HTML文档中
        document.body.appendChild(renderer.domElement)

        // 开启坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);

		const geometry = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
		const geometry1 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
		const geometry2 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
        geometry1.position.x = 3;
        geometry2.position.x = -3;
		scene.add(geometry, geometry1, geometry2);

        // 控制器
        const control = new OrbitControls(camera, renderer.domElement);
        // 开启阻尼惯性,默认值为0.05
        control.enableDamping = true;
       
        // 表示2D vector(二维向量)的类
        const mouse = new THREE.Vector2();

        let geometryArr = [geometry, geometry1, geometry2];
        const raycaster = new THREE.Raycaster();

        // 监听鼠标点击事件
        window.addEventListener("mousedown", (event) => {
            // 转换为一个位于二维空间中的点,在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            console.log(mouse.x, mouse.y);
            // 使用一个新的原点和方向来更新射线
            raycaster.setFromCamera(mouse, camera);
            // 每次点击循环设置物体初始颜色,如不设置会导致点击物体后颜色变后不能再变
            for(const geometry of geometryArr) {
                geometry.material.color.set(0xff0000);
            }
            // 相交的物体变色
            const itgeometrys = raycaster.intersectObjects(geometryArr);
            for(const itgeometry of itgeometrys) {
                itgeometry.object.material.color.set(0xcc33f4);
            }
            
        })

        // 渲染循环动画
        function animate() {
            // 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
            requestAnimationFrame(animate);
          
            // 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
            control.update();
            renderer.render(scene, camera);
        };

        // 执行动画
        animate();
    </script>
</body>
</html>

在学习的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。

标签:Raycaster,Threejs,const,THREE,window,camera,renderer,投射,new
From: https://blog.csdn.net/weixin_44103733/article/details/142140623

相关文章

  • 用Threejs搭建一个Web3D汽车展厅!
    在网页里360度展示它家新款汽车的3d模型,还要可以让用户DIY汽车部件的颜色。先看最终效果3D引擎的基本知识本文的目标是让大家看完之后可以立刻上手用起来,既然要用3d引擎,那我们理解了一些3d的基本知识后,再看threejs的API文档效率就会很高。无论什么3d引擎,都不外乎由以下几种......
  • ThreeJS 综合教程100+【目录】
    ThreeJS综合教程100+旨在为开发者提供两大方面的知识信息:(1)提供详细的每个api知识点的详解(2)提供实战的示例,提供源代码。在这量大系统性的知识下,给用户提供清晰的思路和示例参考,更好的服务于自己的threeJS开发项目。文章正在建设中,下面的是cesium的示例教程(暂时撑门面),随......
  • vue+ThreeJS:从0 到1 搭建开发环境
    文章目录一、下载安装(懒人版)二、顺序安装1,下载安装nodejs2,安装vue-cli3,创建vue-three项目。4,安装threeJS5,安装elementUI(选装)最终package.json文件如下:本系列教程是在vue2.X的基础上加载threeJS程序,来开发各种示例程序。一、下载安装(懒人版)下载vue-three系统包,n......
  • ThreeJs基础
    基本结构场景相机渲染场景用来放入各种网格模型。每个网格模型为独立个体,又几何体和材质组成。投影相机如同人眼,用来观察网格模型。最终利用渲染对象对相机和场景进行渲染,将3D模型渲染在页面上。 创建几何体THREE.BoxGeometry创建立方体constgeometry=newTHREE.......
  • threejs中OrbitControls的用法
    OrbitControls是Three.js库中一个非常流行的相机控制组件,它允许用户通过鼠标(或触控设备)来旋转、缩放和平移场景中的相机,从而从不同的角度和距离观察场景。下面是如何在Three.js中使用OrbitControls的方法:1.引入OrbitControls首先需要从Three.js的CDN或本地路径中引入O......
  • Threejs路径规划案例V1
       最近在做一个路径规划的例子,大概场景是在一个xy坐标系中,有几个障碍物,一个车要绕过这些障碍物到达目的地,本来用java来实现,但是java调试太不直观了,我就想起用threejs把场景简单搭建出来,规划好的路线也直接展示出来,就可以实时查看路径规划的怎么样了。先来一张效果图:首先是添加t......
  • threeJs 修改TransformControls的显示位置
    有的时候模型的原点不是自身中心而是在场景的[0,0,0]位置这个时候想要让TransformControls的位置显示在模型的中心目前找的的处理方式是修改源码找到updateMatrixWorld方法updateMatrixWorld(){...for(leti=0;i<handles.length;i++){ ... if(this......
  • 06--kubernetes.pod管理与投射数据卷
    前言:上一章记录了部署k8s常用的两个方式,这一章就简单一些,整理一下k8s资源对象的配置和管理命令。1、集群状态检查前天搭建的环境,然后关机了两天今天开启后第一时间需要检查集群环境是否正常[root@k8s-master1~]#kubectlgetnodeNAMESTATUSROLESAGE......
  • ThreeJS Shader的效果样例雷达图和大气层(二)
    一、雷达图   实现原理:图中是一个旋转的渐变扇形,可以通过先实现一个扇形、然后再实现一个渐变扇形,最后再将扇形旋转来达到最终效果1. 实现一个夹角为O的扇形,已X轴正方向为单位向量M,UV点到(0,0)形成向量N,通过M和N的点乘就可以得到一个夹角,然后判断角度小于O就可以了2. 实......