当前位置: 首页 > news >正文

Three.js 相机视角的平滑过渡与点击模型切换视角

在 Three.js 中,实现相机视角的平滑过渡和点击模型切换到查看模型视角是一个常见且有用的功能。这种效果不仅能提升用户体验,还能为场景互动添加更多的动态元素。

1. 基本设置

首先,我们需要创建一个基本的 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();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
​
// 创建光源
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 10, 10);
scene.add(light);
添加示例模型
// 创建一个简单的几何体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 1, 0);
scene.add(cube);
​
// 创建另一个几何体
const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(2, 1, 0);
scene.add(sphere);

2. 引入动画库

为了实现平滑过渡,我们引入 tween.js 动画库。

npm install @tweenjs/tween.js
import * as TWEEN from '@tweenjs/tween.js'

3. 实现相机视角的平滑切换

定义相机切换函数
function smoothCameraTransition(targetPosition, targetLookAt) {// 保存当前相机的位置和朝向const startPosition = camera.position.clone();const startLookAt = new THREE.Vector3();camera.getWorldDirection(startLookAt);
​// 创建 tween 动画new TWEEN.Tween(startPosition).to(targetPosition, 2000) // 动画持续时间为2000毫秒.easing(TWEEN.Easing.Quadratic.InOut) // 使用缓动函数.onUpdate(() => {camera.position.copy(startPosition);}).start();
​new TWEEN.Tween(startLookAt).to(targetLookAt, 2000).easing(TWEEN.Easing.Quadratic.InOut).onUpdate(() => {camera.lookAt(startLookAt);}).start();
}
更新渲染循环

确保在渲染循环中更新 tween 动画。

function animate() {requestAnimationFrame(animate);TWEEN.update();renderer.render(scene, camera);
}
animate();

4. 实现点击模型切换视角

添加射线投射器

我们需要添加射线投射器来检测用户点击的模型。

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
​
function onMouseClick(event) {// 将鼠标点击位置转换为标准化设备坐标mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
​// 更新射线投射器raycaster.setFromCamera(mouse, camera);
​// 计算交互对象const intersects = raycaster.intersectObjects(scene.children);
​if (intersects.length > 0) {const intersectedObject = intersects[0].object;// 切换相机视角到点击的模型const targetPosition = new THREE.Vector3().copy(intersectedObject.position).add(new THREE.Vector3(0, 2, 5));const targetLookAt = intersectedObject.position.clone();smoothCameraTransition(targetPosition, targetLookAt);}
}
​
window.addEventListener('click', onMouseClick, false);

5. 完整代码示例

将上述代码片段整合在一起,形成一个完整的示例。

<template><div ref="rendererContainer" class="renderer-container"></div>
</template><script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import TWEEN from '@tweenjs/tween.js';// 引用模板中的 DOM 元素
const rendererContainer = ref(null);// 初始化场景、相机和渲染器
onMounted(() => {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();renderer.setSize(window.innerWidth, window.innerHeight);rendererContainer.value.appendChild(renderer.domElement);const light = new THREE.DirectionalLight(0xffffff, 1);light.position.set(0, 10, 10);scene.add(light);// 添加示例模型const geometry = new THREE.BoxGeometry();const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });const cube = new THREE.Mesh(geometry, material);cube.position.set(0, 1, 0);scene.add(cube);const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);sphere.position.set(2, 1, 0);scene.add(sphere);// 相机平滑过渡函数function smoothCameraTransition(targetPosition, targetLookAt) {const startPosition = camera.position.clone();const startLookAt = new THREE.Vector3();camera.getWorldDirection(startLookAt);new TWEEN.Tween(startPosition).to(targetPosition, 2000).easing(TWEEN.Easing.Quadratic.InOut).onUpdate(() => {camera.position.copy(startPosition);}).start();new TWEEN.Tween(startLookAt).to(targetLookAt, 2000).easing(TWEEN.Easing.Quadratic.InOut).onUpdate(() => {camera.lookAt(startLookAt);}).start();}function animate() {requestAnimationFrame(animate);TWEEN.update();renderer.render(scene, camera);}animate();// 添加射线投射器const raycaster = new THREE.Raycaster();const mouse = new THREE.Vector2();function onMouseClick(event) {mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;raycaster.setFromCamera(mouse, camera);const intersects = raycaster.intersectObjects(scene.children);if (intersects.length > 0) {const intersectedObject = intersects[0].object;const targetPosition = new THREE.Vector3().copy(intersectedObject.position).add(new THREE.Vector3(0, 2, 5));const targetLookAt = intersectedObject.position.clone();smoothCameraTransition(targetPosition, targetLookAt);}}window.addEventListener('click', onMouseClick, false);
});
</script><style>
.renderer-container {width: 100%;height: 100vh;
}
</style>

相关文章:

Three.js 相机视角的平滑过渡与点击模型切换视角

在 Three.js 中&#xff0c;实现相机视角的平滑过渡和点击模型切换到查看模型视角是一个常见且有用的功能。这种效果不仅能提升用户体验&#xff0c;还能为场景互动添加更多的动态元素。 1. 基本设置 首先&#xff0c;我们需要创建一个基本的 Three.js 场景&#xff0c;包括相…...

jenken 打包linux包遇到的问题(环境变量)

环境变量问题 我们jenkens 打包的时候 远程打包 通过ssh 去在服务器上调用脚本 环境变量没有去自动加载 代码打包的时候总是提示相关的so文件找不到 解决方案在 相关程序的make之前 把环境变量加在前面 我这里直接将变量加载代码的最前面...

使用 Go 语言中的 Context 取消协程执行

使用 Go 语言中的 Context 取消协程执行 在 Go 语言中&#xff0c;协程&#xff08;goroutine&#xff09;是一种轻量级的线程&#xff0c;非常适合处理并发任务。然而&#xff0c;如何优雅地取消正在运行的协程是一个常见的问题。本文将通过一个具体的例子来展示如何使用 con…...

python图像彩色数字化

效果展示&#xff1a; 目录结构&#xff1a; alphabets.py GENERAL {"simple": "%#*-:. ","complex": "$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_~<>i!lI;:,\"^. " } # Full list could be found here…...

cesium 3dtile ClippingPlanes 多边形挖洞ClippingPlaneCollection

原理就是3dtiles里面的属性clippingPlanes 采用ClippingPlaneCollection&#xff0c;构成多边形来挖洞。 其次就是xyz法向量挖洞 clippingPlanes: new this.ffCesium.Cesium.ClippingPlaneCollection({unionClippingRegions: true, // true 表示多个切割面能合并为一个有效的…...

docker 僵尸进程问题

docker僵尸进程 子进程结束后&#xff0c;父进程没有回收该进程资源&#xff08;父进程可能没有wait&#xff09;&#xff0c;子进程残留资源存放与内核中&#xff0c;就变为僵尸进程(zombie) 场景分析&#xff1a;python脚本A中执行B应用&#xff0c;将A部署在docker中&#…...

微软要求 Windows Insider 用户试用备受争议的召回功能

拥有搭载 Qualcomm Snapdragon 处理器的 Copilot PC 的 Windows Insider 计划参与者现在可以试用 Recall&#xff0c;这是一项臭名昭著的快照拍摄 AI 功能&#xff0c;在今年早些时候推出时受到了很多批评。 Windows 营销高级总监 Melissa Grant 上周表示&#xff1a;“我们听…...

husky,commit规范,生成CHANGELOG.md,npm发版

项目git提交工程化&#xff08;钩子&#xff0c;提交信息commit message&#xff09;&#xff0c;npm修改版本&#xff0c;需要涉及到的包&#xff1a; husky&#xff0c;允许在git钩子中执行不同的脚步&#xff0c;如commitlint&#xff0c;eslint&#xff0c;prettier&#…...

DETR:一种新颖的端到端目标检测与分割框架

DETR&#xff1a;一种新颖的端到端目标检测与分割框架 摘要&#xff1a; 随着深度学习技术的发展&#xff0c;目标检测和图像分割任务取得了显著的进步。然而&#xff0c;传统的基于区域提名的方法在处理这些问题时存在一定的局限性。为此&#xff0c;Facebook AI Research&am…...

前端js面试知识点思维导图(脑图)

如果看着不清晰可以去https://download.csdn.net/download/m0_73761441/90058523访问下载&#xff0c;无需积分 使用百度脑图制作&#xff0c;可以一键导入下面的文本生成自己的脑图 js相关面试题、知识点 数据类型 1. 数据类型分类&#xff1f;分别包含&#xff…...

【Java基础入门篇】一、变量、数据类型和运算符

Java基础入门篇 一、变量、数据类型和运算符 1.1 变量 计算机中的数据表示方式是&#xff1a;“二进制(0/1)”&#xff0c;但是同时也可以兼容其他进制&#xff0c;例如八进制、十进制、十六进制等。 Java变量的本质是&#xff1a;存储在固定空间的内容&#xff0c;变量名是…...

【llamafactory】安装与环境配置

拉取镜像 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory创建虚拟环境 conda create -n llamafactory python3.10 conda activate llamafactory安装所需依赖 pip install -e ".[torch,vllm,optimum,auto_gptq]"...

Vue 3 + Vuex 埋点实现指南

在现代前端开发中&#xff0c;数据分析和用户行为追踪是不可或缺的部分。本文将介绍如何在 Vue 3 项目中实现埋点功能&#xff0c;具体使用 Vuex 进行状态管理&#xff0c;并通过自定义 Hook 实现埋点逻辑。 目录 项目结构实现埋点逻辑使用埋点功能总结 1.项目结构 我们将创…...

电子应用设计方案-30:智能扫地机器人系统方案设计

智能扫地机器人系统方案设计 一、引言 随着人们生活节奏的加快和对生活品质的追求&#xff0c;智能家居产品越来越受到消费者的青睐。智能扫地机器人作为一种能够自动清扫地面的智能设备&#xff0c;为人们节省了大量的时间和精力。本方案旨在设计一款功能强大、智能化程度高、…...

HTML飞舞的爱心(完整代码)

写在前面 HTML语言实现飞舞的爱心完整代码。 完整代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><title>飞舞爱心</title><style>* {margin: 0;padding: 0;}html,body {overflow: hidd…...

android shader gl_Position是几个分量

在Android的OpenGL ES中&#xff0c;gl_Position是顶点着色器&#xff08;Vertex Shader&#xff09;的一个内置输出变量&#xff0c;它用于指定顶点在裁剪空间&#xff08;Clip Space&#xff09;中的位置。gl_Position是一个四维向量&#xff08;4-component vector&#xff…...

spine 动画层 动态权重

前奏.业务背景 这边想实现一个功能&#xff0c;项目中有 一只猫 猫的头会盯着逗猫棒移动。因为素材还没到所以这里使用了 spine 自带的猫头鹰。他的动画 刚好挺有针对性&#xff1a;&#xff08;关联上篇&#xff09;https://blog.csdn.net/nicepainkiller/article/details/144…...

《Python基础》之Python中可以转换成json数据类型的数据

目录 一、JSON简介 JSON有两种基本结构 1、对象&#xff08;Object&#xff09; 2、数组&#xff08;Array&#xff09; 二、将数据装换成json数据类型方法 三、在Python中&#xff0c;以下数据类型可以直接转换为JSON数据类型 1、字典&#xff08;Dictionary&#xff09…...

在oracle下载jdk显示400 Bad Request Request Header Or Cookie Too Large

下载JDK17&#xff0c;官网地址&#xff1a;【https://www.oracle.com/cn/java/technologies/downloads/#jdk17-windows】 问题&#xff1a; 出现 400 Bad Request: Request Header Or Cookie Too Large 错误&#xff0c;通常是由于浏览器存储的 Cookies 或请求头过大所导致的…...

MongoDB注入攻击测试与防御技术深度解析

MongoDB注入攻击测试与防御技术深度解析 随着NoSQL数据库的兴起&#xff0c;MongoDB作为其中的佼佼者&#xff0c;因其灵活的数据模型和强大的查询能力&#xff0c;受到了众多开发者的青睐。然而&#xff0c;与任何技术一样&#xff0c;MongoDB也面临着安全威胁&#xff0c;其…...

【Java基础入门篇】前言

Java基础入门篇 本系列内容主要针对Java基础知识&#xff0c;总共包含四大部分内容&#xff1a; 变量、数据类型和运算符控制语句和递归算法面向对象和JVM底层分析数组和排序 学习需要具备&#xff1a; IDEA编译器 JDK1.8版本 写在前面 在Java入门的最开始&#xff0c;我们需…...

Oracle 建表的存储过程

建表的存储过程 下面是建表的存储过程&#xff0c;用途&#xff1a;通过不同的表&#xff0c;根据不同过滤条件&#xff0c;得到某个字段&#xff0c;例如neid&#xff0c;然后创建一个新表T&#xff0c;表T的表名为拼接XXXX_XXX_neid&#xff0c;表T的字段自行添加 xxx&…...

【Debug】hexo-github令牌认证 Support for password authentication was removed

title: 【Debug】hexo-github令牌认证 date: 2024-07-19 14:40:54 categories: bug解决日记 description: “Support for password authentication was removed on August 13, 2021.” cover: https://pic.imgdb.cn/item/669b38ebd9c307b7e9f3e5e0.jpg 第一章 第一篇博客记录一…...

torch.is_floating_point(input)

torch.is_floating_point(input) input: 输入张量 如果输入的数据类型是 浮点数据类型 ,则返回 True。否则返回False。 浮点数据类型&#xff1a;torch.float64、torch.float32、torch.float16 、 torch.bfloat16 import torch# 创建一个浮点数张量 float_tensor torch.te…...

【分布式】分布式事务

目录 1、事务的发展 2、本地事务 &#xff08;1&#xff09;如何保障原子性和持久性&#xff1f; &#xff08;2&#xff09;如何保障隔离性&#xff1f; 2、全局事务 &#xff08;1&#xff09;XA事务的两段式提交 &#xff08;2&#xff09;XA事务的三段式提交…...

Spring Data 简介

Spring Data 是一个用于简化数据库访问的框架&#xff0c;它是 Spring 生态系统中的重要组成部分。以下是详细介绍&#xff1a; 一、背景和目的 在开发应用程序时&#xff0c;数据访问层的实现往往是比较复杂和繁琐的。开发人员需要编写大量的代码来实现诸如数据库连接、查询…...

【娱乐项目】基于批处理脚本与JavaScript渲染视频列表的Web页面

Demo介绍 一个简单的视频播放器应用&#xff0c;其中包含了视频列表和一个视频播放区域。用户可以通过点击视频列表中的项来选择并播放相应的视频&#xff0c;播放器会自动播放每个视频并在播放完毕后切换到下一个视频。本项目旨在通过自动化脚本和动态网页渲染&#xff0c;帮助…...

[MySQL]流程控制语句

流程控制语句需要借助存储过程才有效。关于存储过程&#xff0c;我会在后续的文章详述&#xff0c;本篇文章只是阐述流程控制语句。因此&#xff0c;大家只需要注意存储过程中相应的流程控制语句即可。 如果文中阐述不全或不对的&#xff0c;多多交流。 参考笔记三&#xff0c…...

Flink在Linux系统上的安装与入门

一、Flink的引入 这几年大数据的飞速发展&#xff0c;出现了很多热门的开源社区&#xff0c;其中著名的有Hadoop、Storm&#xff0c;以及后来的Spark&#xff0c;他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河&#xff0c;也以内存为赌注&#xff0c;赢得了内存计…...

微信小程序Webview与H5通信

背景 近期有个微信小程序需要用到web-view嵌套H5的场景&#xff0c;该应用场景需要小程序中频繁传递数据到H5进行渲染&#xff0c;且需要保证页面不刷新。 由于微信小程序与H5之间的通信限制比较大&#xff0c;显然无法满足于我的业务场景 探索 由于微信小程序与webview的环境是…...

武夷山网站推广/廊坊百度推广seo

大部分行业只要做好了就能获得收益&#xff0c;无论前端还是后端&#xff0c;优秀的程序员还是很受公司欢迎的。 下面是某招聘网上北京海淀地区web前端的招聘量&#xff1a; 500的职位证明web前端的需求量还是不少的。只要技术过关&#xff0c;找到一份工作还是没有问题的。 …...

合肥建站网站平台/搜狗提交入口网址

重庆思庄12cOCP11月14即将开课&#xff0c;正火热报名&#xff01;思庄课程以提升操作能力为主&#xff0c;课上辅以大量实例练习&#xff0c;专家指导上机&#xff0c;真正的学以致用。课程又紧贴OCP认证考试&#xff0c;完成本课程学员完全具备轻松通过OCP认证的能力&#xf…...

wordpress汉化包安装/职业培训机构需要什么资质

完善了技能动画。状态判断。等等。...

学院网站设计模板/seoul是什么意思中文

近来一直用Typora这个神器写东西&#xff0c;感觉相当好&#xff0c;但新建一个文件的时候总是要右键新建一个txt文件&#xff0c;然后再改后缀&#xff0c;这样子还蛮烦的&#xff0c;因此最好的做法是右键直接就能新建一个md文件。实现如下&#xff0c;新建一个txt文件&#…...

wordpress 字符替换插件/北京网站托管

1.每早一更新&#xff0c;提交前更新 git pull -u origin master: master&#xff08;master为分支名称&#xff09; 2.每晚一提交&#xff1a; git add . &#xff08;注&#xff1a;别忘记后面的.此操作是把文件夹下面的文件都添加进来&#xff09; git commit -m "提交…...

网站开发建设合同/今日十大热点新闻事件

2019独角兽企业重金招聘Python工程师标准>>> Pipelines 管道 管道是Redis的子类&#xff0c;它支持缓冲多个命令&#xff0c;一次性发送到服务器去执行。可以大大的提高性能&#xff0c;减少服务器到客户端之间的TCP来回数据包。 管道的简单使用: >>> r r…...