three.js 鼠标左右拖动改变玩家视角

这里主要用到了 一个方法 obj.getWorldDirection();
obj.getWorldDirection()表示的获取obj对象自身z轴正方向在世界坐标空间中的方向。
按下 W键前进运动;
<template><div><el-container><el-main><div class="box-card-left"><div id="threejs"></div>{{ movementX }}</div></el-main></el-container></div>
</template>s
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import TWEEN from '@tweenjs/tween.js';
export default {data() {return {scene: null,camera: null,renderer: null,res1: null,res2: null,clock: null,left_mouse_down: false,keyState: {W: false,S: false,A: false,D: false,},left_rotation: true, // 向左旋转的标志right_rotation: true, // 向右旋转的标志VW: new this.$three.Vector3(0, 0, 0),VS: new this.$three.Vector3(0, 0, 0),curr_v: new this.$three.Vector3(0, 0, 0),person: null,movementX: null,deltaTime: 0,a: 60, // 加速度damping: -0.04,};},created() {},mounted() {this.init();},methods: {goBack() {this.$router.go(-1);},init() {// 创建场景对象this.scene = new this.$three.Scene();// 创建坐标轴辅助对象const axesHelper = new this.$three.AxesHelper(100);this.scene.add(axesHelper);// 创建时钟对象this.clock = new this.$three.Clock();// 创建环境光对象const ambientLight = new this.$three.AmbientLight(0xffffff, 6);this.scene.add(ambientLight);// this.createMesh();// 创建相机对象this.camera = new this.$three.PerspectiveCamera(60,1,0.01,2000);// this.camera.position.set(0,5,-5);// this.camera.lookAt(0,0,0);// 创建渲染器对象this.renderer = new this.$three.WebGLRenderer();this.renderer.setSize(1000,800);// 创建gltfLoader加载器对象const gltfLoader = new GLTFLoader();gltfLoader.load("models/gltf/person2/scene.gltf", gltf => {this.person = gltf.scene;// 将相机添加到人物模型上this.person.add(this.camera);// 调整相机位置this.camera.position.add(new this.$three.Vector3(0,5,-6));this.camera.translateZ(-1);let camera_look_position = this.person.position.clone().add(new this.$three.Vector3(0,4,0));// 设置相机指向this.camera.lookAt(camera_look_position);this.scene.add(gltf.scene);this.renderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.renderer.domElement);})// 监听事件方法this.addEventListenerFn();this.renderLoop();},createMesh() {const geometry = new this.$three.BoxGeometry(1,1,1);const material = new this.$three.MeshBasicMaterial({color: 0xffaadd});const mesh = new this.$three.Mesh(geometry, material);// mesh.rotateY(Math.PI / 2);const dir = new this.$three.Vector3();mesh.getWorldDirection(dir);this.scene.add(mesh);console.log('dir', dir);},addEventListenerFn() {document.addEventListener("mousemove", e => {// 鼠标左键按下的情况if(this.left_mouse_down) {this.movementX = e.movementX;this.person.rotation.y -= e.movementX / 100;// this.camera.rotateY(e.movementX / 100);const dir = new this.$three.Vector3();this.person.children[0].getWorldDirection(dir);this.renderer.render(this.scene, this.camera);}})document.addEventListener("mousedown", e => {// e.button == 0 左键;e.button == 2 右键;if(e.button == 0) {this.left_mouse_down = true;}})document.addEventListener("mouseup", e => {// e.button == 0 左键;e.button == 2 右键;if(e.button == 0) {this.left_mouse_down = false;}})// 监听键盘按下document.addEventListener("keydown", e => {// 如果按下的是 w键if(e.code == "KeyW") {this.keyState.W = true;}if(e.code == "KeyS") {this.keyState.S = true;}})// 监听键盘弹起document.addEventListener("keyup", e => {// 如果按下的是 w键if(e.code == "KeyW") {this.keyState.W = false;}if(e.code == "KeyS") {this.keyState.S = false;}})},renderLoop() {let deltaTime = this.clock.getDelta();if(this.keyState.W) {const front = new this.$three.Vector3();this.person.getWorldDirection(front);let person_v = this.curr_v.clone().add(front.multiplyScalar(deltaTime * this.a));const pos = person_v.clone().multiplyScalar(deltaTime);this.person.position.add(pos);}if(this.keyState.S) {const front = new this.$three.Vector3();this.person.getWorldDirection(front);let person_v = this.curr_v.clone().add(front.multiplyScalar(deltaTime * (-this.a)));const pos = person_v.clone().multiplyScalar(deltaTime);this.person.position.add(pos);}this.renderer.render(this.scene, this.camera);window.requestAnimationFrame(this.renderLoop);},},
};
</script>
<style lang="less" scoped>
.box-card-left {display: flex;align-items: flex-start;flex-direction: row;width: 100%;.box-right {img {width: 500px;user-select: none;}}
}
</style>
相关文章:
three.js 鼠标左右拖动改变玩家视角
这里主要用到了 一个方法 obj.getWorldDirection(); obj.getWorldDirection()表示的获取obj对象自身z轴正方向在世界坐标空间中的方向。 按下 W键前进运动; <template><div><el-container><el-main><div class"box-card-left…...
Pycharm jupyter server process exited with code 1
Pycharm jupyter server process exited with code 1 1. 问题描述2. 原因和解决方法 1. 问题描述 使用 Pycharm 启动 Jupyter 时,报错如下, jupyter server process exited with code 12. 原因和解决方法 Pycharm 启动 jupyter 时,默认的 …...
ubuntu 20.04 Python pip 配置 pip.conf
1. 状况描述 $ pip install timm WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by ProxyError(Cannot connect to proxy., RemoteDisconnected(Remote end closed connection without response)): /simple/t…...
GPT-4.5 Turbo意外曝光,最快明天发布?OpenAI终于要放大招了!
大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,所以创建了“AI信息Gap”这个公众号,专注于分享AI全维度知识…...
Ubuntu 中 desktop-amd64 和 live-server-amd64 的区别
一、Ubuntu的操作系统镜像 Ubuntu的操作系统镜像主要有两种:desktop-amd64和live-server-amd64 这两者的主要区别在于使用场景和安装方式 1. Desktop-amd64: * 这是Ubuntu的桌面版本,用于安装具有图形用户界面的Ubuntu系统。 * 它包含了用于日常使…...
第10集《天台教观纲宗》
请大家打开讲义第十七页。我们讲到己二、结申正义。 己二、结申正义 《法华经》把我们修行人修行的相貌,比喻作一个车乘。车乘就是一种交通工具,它能够让我们从此岸超越到彼岸去。所以修行它是可以超越的,你今天比昨天超越了,就好…...
每日学习笔记:C++ STL 的forward_list
定义 特点 操作函数 元素查找、移除或安插 forward_list::emplace_after arg...指的是元素构造函数的参数(0~N个) #include <iostream> #include <memory> #include <list> #include <forward_list> using namespace std;class…...
【Java,Redis】Redis 数据库存取字符串数据以及类数据
1、 字符串存取数据 Resource private StringRedisTemplate stringRedisTemplate;//从Redis中获取string字符串 stringRedisTemplate.opsForValue().get("cache:shop:"id); //Json -> class Shop shop JSONUtil.toBean(ShopJson,Shop.class); //字符串写入redis…...
OpenCV 图像重映射函数remap()实例详解
OpenCV 图像重映射函数remap()对图像应用通用几何变换。其原型如下: void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode BORDER_CONSTANT, const Scalar & borde…...
Python基础课堂最后一课23——正则对象
文章目录 前言一、正则对象是什么?二、正则表达式基本分类1.普通字符2.元字符 总结 前言 很开心能和你们一些学习进步,在这一个多月的时间中,是你们让我坚持了下来,完成了python基础课堂编写,不管如何,我们…...
【算法训练营】凸包,图(Python实现)
凸包 描述 给定n个二维平面上的点,求他们的凸包。 输入 第一行包含一个正整数n。 接下来n行,每行包含两个整数x,y,表示一个点的坐标。 输出 令所有在凸包极边上的点依次为p1,p2,...,pm(序号),其中m表…...
webpack5零基础入门-6webpack处理图片资源
1.在webpack5中file-loader和url-loader为内置模块 通过在加载器中配置rule即可激活 {test: /\.(png|jpe?g|gif|webp)$/,type: asset} 2.使用webpack进行打包 执行npx webpack 可以看到图片资源打包后都被放到了dist文件目录下 3.使用webpack进行图片格式转换为base64 优势…...
计算机基础知识QA
目录 数据库 --mysql 关联查询 唯一索引如何创建,语句 更新表字段语句 查看字段类型 --redis 使用场景 数据结构 设置超时时间 linux 常用命令 发布版本 安装一个东西,发现一个东西安装的很慢,如何切换ip地的源?-&g…...
微信小程序一次性订阅requestSubscribeMessage授权和操作详解
一次性订阅:用户订阅一次发一次通知 一、授权 — requestSubscribeMessage Taro.requestSubscribeMessage({tmplIds: [], // 需要订阅的消息模板的id的集合success (res) {console.log("同意授权", res)},fail(res) {console.log(拒绝授权, res)}})点击或…...
ARM 汇编指令:(三)运算处理指令
目录 一.add指令 二.sub指令 三.MUL指令 一.add指令 add用于执行实现两个寄存器或寄存机或寄存器与立即数的相加操作。它可以用于整数、浮点数等各种数据类型的加法运算。 ADD{cond}{S} Rd,操作数,操作数 1.不带进位加法指令add add r1, r2, #4 //r1 r2 4 add r1, r2 …...
【C++庖丁解牛】STL简介 | string容器初次见面
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1. 什么是STL2. STL的版本…...
记OnlyOffice的两个大坑
开发版,容器部署,试用许可已安装。 word,ppt,excel均能正常浏览。 自带的下载菜单按钮能用。 但config里自定义的downloadAs方法却不一而足。 word能正常下载,excel和ppt都不行。 仔细比对调试了代码。发现app.js…...
分享几个Google Chrome谷歌浏览器历史版本下载网站
使用selenium模块的时候,从官网下载的谷歌浏览器版本太高,驱动不支持,所以需要使用历史的谷歌浏览器版本 ,这里备份一下以防找不到了。 驱动下载地址:https://registry.npmmirror.com/binary.html?pathchromedriver 文…...
备考2025年AMC8竞赛:吃透2000-2024年600道真题(免费赠送真题)
我们继续来随机看五道AMC8的真题和解析,根据实践经验,对于想了解或者加AMC8美国数学竞赛的孩子来说,吃透AMC8历年真题是备考最科学、最有效的方法之一。 即使不参加AMC8竞赛,吃透了历年真题600道和背后的知识体系,那么…...
考研复试C语言篇
第一章 概述 1.1什么是程序 为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的合集。 1.4C语言的特点 代码级别的跨平台:由于标准的存在,使得几乎同样的C代码可用于多种操作系统,也适用于多种机型。使允许直接访问物理地址…...
Windows下用mklink命令迁移谷歌浏览器到D盘(附详细步骤图)
Windows系统迁移谷歌浏览器的终极方案:mklink命令深度解析 你是否也遇到过C盘空间告急的窘境?作为开发者日常必备工具的谷歌浏览器,随着缓存和扩展程序的不断累积,往往会占据大量系统盘空间。本文将带你深入探索Windows系统中mkli…...
从天气预报到股票分析:用Python实战理解随机过程与概率论基础
从天气预报到股票分析:用Python实战理解随机过程与概率论基础 天气预报的准确率为何忽高忽低?股票价格的波动背后隐藏着怎样的数学规律?这些看似不相关的问题,其实都指向同一个核心概念——随机过程。作为概率论的延伸,…...
从TCP BBR到网卡中断绑定:给K8s节点和游戏服务器做一次网络延迟‘大保健’
从TCP BBR到网卡中断绑定:给K8s节点和游戏服务器做一次网络延迟‘大保健’ 在云原生和高性能计算领域,网络延迟的毫秒级波动可能引发连锁反应——Kubernetes集群中某个Pod的响应延迟会导致整个微服务链路雪崩,而游戏服务器上50ms的卡顿足以让…...
GCC/Clang编译警告终极配置:用-Wall -Wextra提升代码质量的3个冷技巧
GCC/Clang编译警告终极配置:用-Wall -Wextra提升代码质量的3个冷技巧 在C/C开发中,编译警告常被视为"可以忽略的噪音",但经验丰富的开发者知道,这些警告往往是代码质量的早期预警系统。当你在深夜调试一个难以复现的内存…...
SQL Server导入导出向导报错终极指南:从驱动安装到版本兼容性全解析
SQL Server数据迁移全链路排错手册:从驱动配置到跨版本适配实战 当你第5次看到"未在本地计算机上注册Microsoft.ACE.OLEDB.12.0提供程序"的红色报错框时,是否想过这背后隐藏着SQL Server数据迁移的完整知识体系?数据工程师老张最近…...
适配器模式设计思路
01.适配器模式基础适配器模式是一种结构型设计模式,用于将不兼容的接口转换为可兼容的接口,使原本不能一起工作的类可以协同工作。本文详细介绍了适配器模式的基础、实现方式(类适配器和对象适配器)、应用场景(如封装有…...
飞书机器人集成OpenClaw与百川2-13B-4bits量化版:对话触发任务实战
飞书机器人集成OpenClaw与百川2-13B-4bits量化版:对话触发任务实战 1. 为什么选择这个技术组合 去年冬天,我接手了一个小团队的内部效率优化项目。团队每天需要从海量行业报告中提取关键数据,整理成简报表。最初尝试用传统RPA工具ÿ…...
4月,新一轮发票抽奖,请收好这份开具发票指南!!
4月,重庆发票抽奖新的一轮发票抽奖已经了(目前第三轮)。你所在的城市不知道是不是也是第三期发票抽奖了。发票抽奖首先需要发票。发票除了线下直接找商家开具外,我们也可以在线上直接开具。这份发票开具指南,归纳总结我…...
19c升级遇见错误,libclntsh.so.19.1和libasmclntsh19.so
错误内容:Details: [ ---------------------------Patching Failed--------------------------------- Command execution failed during patching in home: /oracle/app/19.3.0/grid, host: efb01. Command failed: /oracle/app/19.3.0/grid/OPatch/opatchauto a…...
OpenClaw性能优化:降低千问3.5-9B调用的Token消耗
OpenClaw性能优化:降低千问3.5-9B调用的Token消耗 1. 为什么需要关注Token消耗 去年冬天我第一次用OpenClaw对接千问3.5-9B模型时,被账单吓了一跳——一个简单的文件整理任务竟然消耗了将近2万Token。这让我意识到,在本地部署场景下&#x…...
