THREE.JS镜头随鼠标晃动效果

请添加图片描述
为了让动画更灵活并且简单 借助gsap让其具有更多可能,在未来更容易扩充其他动效
gsap Dom跟随鼠标移动 gsap.quickTo()


首先要监听鼠标移动,并且将移动的值转换到 -1 和 1 之间 方便处理
 private mousemove(e: MouseEvent) {const x = (e.clientX / innerWidth) * 2 - 1;const y = (e.clientY / innerHeight) * 2 - 1;}

这样将 位置 / 屏幕宽高 将值缩放在 0 和 1之间
然后通过 乘2减1 将其限制在-1 和 1之间

 private mousemove(e: MouseEvent) {const x = ((e.clientX / innerWidth) * 2 - 1) * 2 - 1;const y = ((e.clientY / innerHeight) * 2 - 1) * 2 - 1;}

在three中y轴 上面是1下面是-1 而我们窗口上面是-1 下面是1 所以取y轴剩余的高度让两者行为统一,也就是实现向着鼠标方向

 private mousemove(e: MouseEvent) {const x = ((e.clientX / innerWidth) * 2 - 1) * 2 - 1;const y = (((innerHeight - e.clientY) / innerHeight) * 2 - 1) * 2 - 1;}

如此 我们获取了鼠标移动的增量,将这一向量加在camera的x和y轴即可,这里不能使用+=这样会越来越偏 所以保存相机的原始位置。那么当前鼠标所在相机的位置,应当是原始位置加上鼠标移动的增量
这里就可以使用gsap来控制position变化

private xQuickTo = gsap.quickTo(this.camera.position, "x", {duration: 0.5,
});

上述代码 this.camera.position.x 经过0.5秒后变化到传入值,如:this.xQuickTo(this.cameraPosition.x + x)

class Shake {cameraPosition = this.camera.position.clone();private xQuickTo = gsap.quickTo(this.camera.position, "x", {duration: 0.5,});private yQuickTo = gsap.quickTo(this.camera.position, "y", {duration: 0.5,});private mousemove(e: MouseEvent) {const x = ((e.clientX / innerWidth) * 2 - 1) / this.amplitude;const y =(((innerHeight - e.clientY) / innerHeight) * 2 - 1) /this.amplitude;this.xQuickTo(this.cameraPosition.x + x).play();this.yQuickTo(this.cameraPosition.y + y).play();}}

如此 核心逻辑便完成,丰富事件监听并且加入振幅,控制相机移动范围 后完成这个class

export class Shake {/** 振幅 鼠标晃动的影响 */amplitude = 1;cameraPosition = this.camera.position.clone();private xQuickTo = gsap.quickTo(this.camera.position, "x", {duration: 0.5,});private yQuickTo = gsap.quickTo(this.camera.position, "y", {duration: 0.5,});constructor(public camera: THREE.Camera, public domElement: HTMLElement) {this.domElement.addEventListener("mousemove", this.selfMouseMove);}private mousemove(e: MouseEvent) {const x = ((e.clientX / innerWidth) * 2 - 1) / this.amplitude;const y =(((innerHeight - e.clientY) / innerHeight) * 2 - 1) /this.amplitude;this.xQuickTo(this.cameraPosition.x + x)this.yQuickTo(this.cameraPosition.y + y)}private selfMouseMove = (e: MouseEvent) => this.mousemove.call(this, e);destroyMouseMove() {this.domElement.removeEventListener("mousemove", this.selfMouseMove);}
}

接下来可以扩充一下功能, 加入鼠标按下时可以拖拽旋转,鼠标松开后回到原来的位置
为了支持这些功能 需要给shake增加暂停动画的能力


export class Shake {pause = false;/** 振幅 鼠标晃动的影响 */amplitude = 1;cameraPosition = this.camera.position.clone();xQuickTo = gsap.quickTo(this.camera.position, "x", {duration: 0.5,});yQuickTo = gsap.quickTo(this.camera.position, "y", {duration: 0.5,});private yQuickToTween: gsap.core.Tween | undefined;private xQuickToTween: gsap.core.Tween | undefined;point = new Vector2();constructor(public camera: THREE.Camera, public domElement: HTMLElement) {this.domElement.addEventListener("mousemove", this.selfMouseMove);}private mousemove(e: MouseEvent) {if (this.pause) {this.xQuickToTween && this.xQuickToTween.pause();this.yQuickToTween && this.yQuickToTween.pause();return;}//  -1 ~ 1const x = ((e.clientX / innerWidth) * 2 - 1) / this.amplitude;const y =(((innerHeight - e.clientY) / innerHeight) * 2 - 1) /this.amplitude;this.point.set(x, y);this.xQuickToTween = this.xQuickTo(this.cameraPosition.x + x);this.yQuickToTween = this.yQuickTo(this.cameraPosition.y + y);}private selfMouseMove = (e: MouseEvent) => this.mousemove.call(this, e);destroyMouseMove() {this.domElement.removeEventListener("mousemove", this.selfMouseMove);}
}
export class CameraShake extends Shake {constructor(...params: ConstructorParameters<typeof Shake>) {super(...params);this.domElement.addEventListener("mousedown", this.selfMouseDown);}mousedown() {if (this.pause) return;this.pause = true;document.addEventListener("mouseup", this.selfMouseUp, { once: true });}mouseup() {const { x, y, z } = this.cameraPosition;gsap.to(this.camera.position, {x: x + this.point.x,y: y + this.point.y,z,duration: 0.8,onComplete: () => {this.pause = false;},});}selfMouseDown = () => this.mousedown.call(this);selfMouseUp = () => this.mouseup.call(this);destroyMouseEvent() {this.destroyMouseMove();this.domElement.removeEventListener("mousedown", this.selfMouseDown);}
}

ok 上述代码将支持轨道控制器 旋转回来能力


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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP 协议的基本格式

目录 1.基本格式 首行 请求报头 关于cookie 关于Referer 响应的报文 首行 关于状态码 1.基本格式 让我们来看看fiddler抓包的下的实际报文情况 首行 在http1.1中&#xff0c;有如下方法 POST、GET、HEAD、PUT、OPTIONS、DELETE、TRACE、CONNECT 在我们抓包遇到的环境中&…

js深拷贝、js使用递归实现深拷贝

相信看到这篇文章之前你应该多多少少了解过什么是深拷贝了为什么要什么拷贝了 这里就不介绍什么是深拷贝、浅拷贝了 最优解深拷贝方法&#xff1a;递归 这里为了方便直接在vue的页面里面演示了&#xff0c;在其他js文件中使用注意下this mounted() {const obj {str: "字…

Elasticsearch【集群概念、搭建集群】(七)-全面详解(学习总结---从入门到深化)

目录 Elasticsearch集群_概念 Elasticsearch集群_搭建集群 Elasticsearch集群_概念 在单台ES服务器上&#xff0c;随着一个索引内数据的增多&#xff0c;会产生存储、效率、安全等问题。 1、假设项目中有一个500G大小的索引&#xff0c;但我们只有几台200G硬盘 的服务器&am…

windows凭据收集

实验目的 掌握windows凭据的收集方法 实验环境 windows server 2008 实验工具 mimikatz procdump 实验原理 用户凭证获取&#xff0c;一般是指 ntlm hash 或者可以直接利用的明文密码。 实验内容 使用mimikatz获取用户信息 使用procdump获取当前用户的明文密码 实验步骤…

RabbitMQ在SpringBoot中的高级应用(2)

过期时间 1.单独的设置队列的存活时间,队列中的所有消息的过期时间一样 Bean//创建交换机public DirectExchange ttlQueueExchange(){// 交换机名称 是否持久化 是否自动删除return new DirectExchange("ttl_queue_log",true,false);}Bean//创建队列publ…

若依@DataScope

DataScope &#xff1a; 根据sys_role 中的 data_scope中的值&#xff0c;来设置数据该怎么过滤&#xff0c;&#xff0c; data_scope 取值&#xff1a; 1 &#xff1a; 不需要过滤2 &#xff1a; 自定义过滤 &#xff1a; 根据 sys_role_dept 这个表关联出来的 dept_id 过滤…

函数指针数组的概念和应用

函数指针数组 是什么&#xff1f; 函数指数组是存放函数指针的数组 int Add(int x, int y) {return x y; }int Sub(int x, int y) {return x - y; }int Mul(int x, int y) {return x * y; }int Div(int x, int y) {return x / y; }int main() {int(*parr[4])(int, int) { …

Ubuntu 20.04 LTS 安装 nvidia 驱动 + cuda 11.8 从开始到放弃!

升级 sources.list # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restri…

回归预测 | MATLAB实现WOA-DNN鲸鱼算法优化深度神经网络的数据多输入单输出回归预测

回归预测 | MATLAB实现WOA-DNN鲸鱼算法优化深度神经网络的数据多输入单输出回归预测 目录 回归预测 | MATLAB实现WOA-DNN鲸鱼算法优化深度神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 回归预测 | MATLAB实现WOA-DNN鲸鱼算法优化深度…

什么是Qt Widgets?一组创建经典桌面应用UI的界面组件!

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 Qt Widgets模块提供…

spring-依赖注入的方式

setter注入-可选依赖注入 简单类型&#xff1a; 1.配置类 2.set方法 引用类型&#xff1a; 构造器注入-强制依赖注入 简单类型&#xff1a; 引用类型&#xff1a; 通过有参构造&#xff0c;获得需要注入的对象 <construct-arg />标签中name属性中填写的时构造方…

Linux--进程

什么叫做进程&#xff1f; 程序加载到内存就叫进程&#xff08;看不懂是吧&#xff0c;看下面更详细一些&#xff09; 进程对应的代码和数据进程对应的PCB结构体