当前位置: 首页 > 编程日记 > 正文

js判断鼠标靠近屏幕最侧面的监听_threejs按鼠标位置缩放场景

e0d15cae8211b84c4b6ef97de833123f.png

threejs的orbitcontrol,默认的缩放模式为整体以target为中心进行缩放。有时候,我们想让场景按照鼠标位置进行缩放,体验起来就和地图的缩放一样,最直观的感觉就是整个场景会越来越靠近鼠标点的位置,而不是整体的缩放大小。

问题描述

我们通过一个具体的例子来看看二者的区别。比如我们有如下场景,场景的相机target在平面的左下角,当我们缩放整个场景的时候,threejs的默认情况会整体按照target的位置缩放场景。

threejs默认缩放形式

3afe9e8c33a5f8cea3ec3bac36f57cbd.gif

可以看到,threejs默认的缩放形式,并没有考虑鼠标位置,也就是无论你鼠标放在那里,其实滚轮缩放的时候场景缩放的感觉是一样的。对比下下面的按鼠标点位置缩放,我们来看看。

按鼠标点位置缩放

456b3dd9f0c98dce1e225fce1e981cad.png

从动图上我们可能看出来,以鼠标点为中心缩放的结果就是,我们鼠标点所在的位置被考虑进了缩放里。我们的缩放会让鼠标点所在的位置缩放的更大。这样更加符合用户的使用习惯,也就是用户鼠标所在的位置是用户更加关心的位置,希望相机更加偏向鼠标点的位置。

如何实现

ok,既然看完了对比,我们就来说下如何实现以鼠标点位置为缩放中心的场景缩放。我们以threejs中最常用的orbitcontrol为例子,来讲下如果达到我们想要的效果。

我们先来找到orbitcontrol中关于鼠标滚轮的处理函数,大致如下所示:

function handleMouseWheel( event ) {if ( event.deltaY < 0 ) {dollyIn( getZoomScale() );} else if ( event.deltaY > 0 ) {dollyOut( getZoomScale() );}scope.update();
}

可以看到这里滚轮处理的函数非常简单,判断下滚轮滚动的方向,然后执行缩放,最后更新control。

function handleMouseWheel( event ) {//设置相机缩放比数值越大缩放越明显let factor = 15;//从鼠标位置转化为webgl屏幕坐标位置let glScreenX = (event.clientX / scope.domElement.width) * 2 - 1;let glScreenY = -(event.clientY / scope.domElement.height) * 2 + 1;let vector = new Vector3(glScreenX, glScreenY, 0);//从屏幕向量转为3d空间向量vector.unproject(scope.object);//相机偏移量vector.sub(scope.object.position).setLength(factor);if (event.deltaY < 0) {scope.object.position.add(vector);scope.target.add(vector);} else {scope.object.position.sub( vector);scope.target.sub(vector);}scope.update();}

代码非常的简单,主要原理就是让相机沿着鼠标位置的偏移量进行偏移。(缩放只是拉近拉远相机)

除了以上的直接修改contro的源码以外,我们其实还可以自己直接监听dom的事件,然后设置control的enableZoom值为false禁止默认缩放,自己再业务代码中实现。只是把代码的位置换了下,这样可以尽量少的修改第三方库源码,以免后期升级时,需要额外的merge代码。

线上demo地址

OrbitControls修改版

参考: Stack Overflow

相关文章:

hibernate中多对多分解成一对多,

1&#xff0c;参考&#xff1a;http://blog.csdn.net/yaerfeng/article/details/6969632

C++ 函数参数 值传递与引用传递

以前我们在C语言中函数参数传递过程中&#xff0c;如果我们想要让当A函数作用域中的变量经过B函数处理之后的数值仍然在A函数中生效&#xff0c;这个时候函数参数的传递时需要引用方式去传递&#xff0c;方式如下&#xff1a; #include <stdio.h> //函数参数为指针&…

SharePoint 2013 图文开发系列之代码定义列表

在SharePoint的开发中&#xff0c;用Visual Studio自定义列表是经常会用到的&#xff0c;因为很多时候&#xff0c;我们并不会手动创建列表&#xff0c;而手动创建列表在测试服务器和正式机之间同步字段&#xff0c;也很麻烦&#xff0c;所以我们经常用代码来定义列表或者文档库…

arduino下载库出错_【arduino】DIY音乐播放器,arduino播放wav音乐,TRMpcm库测试及使用...

微信关注 “DLGG创客DIY”设为“星标”&#xff0c;重磅干货&#xff0c;第一时间送达。arduino特点库超多&#xff0c;想必大家都领教了&#xff0c;今天来分享一下之前玩过的TRMpcm库。这个库是干嘛用的&#xff1f;简单粗暴用arduino(这里特指arduino官方那几个板子uno、nan…

vim替换技巧4

、 转自&#xff1a;http://www.confay.com/2008/03/vim4.html [技巧一] 第一个是在VIM邮件列表中看到的&#xff0c;给出了一个如何统计文章字数的方法。 统计一个完整文件的字数&#xff0c;可以使用Unix下的wc工具&#xff0c;它能够统计一个文件的行数、单词数和字符数。 如…

spark1.x和2.xIterable和iterator兼容问题

1. spark 1.x 升级到spark 2.x 对于普通的spark来说,变动不大 : 1 举一个最简单的实例:spark1.x public static JavaRDD<String> workJob(JavaRDD<String> spark1Rdd) {JavaPairRDD<String, Integer> testRdd spark1Rdd.flatMapToPair(new PairFlatMapFunct…

C++ 拷贝构造函数和重载赋值运算符的区别

文章目录拷贝构造函数重载赋值运算符赋值运算符和拷贝构造函数最大区别是赋值运算符没有新的对象生成&#xff0c;而拷贝构造函数会生成新的对象。 为了更加形象 准确得描述 赋值运算符和拷贝构造函数得区别&#xff0c;将详细通过代码展示两者之间得差异。 拷贝构造函数 首先…

单元格内多个姓名拆分成一列_EXCEL拆分单元格中的姓名,这都不叫事儿

作者&#xff1a;祝洪忠 转自&#xff1a;Excel之家ExcelHome小伙伴们好啊&#xff0c;今天老祝和大家来分享一个数据整理的技巧。下面的表格形式&#xff0c;想必大家不会陌生吧&#xff1a;在这个表格内&#xff0c;同一个部门的人员名单都挤到一个单元格内。现在问题来了&am…

3.1 A Historical Perspective 历史观点

1.从1978年的8086到现在的2008年core i7 ,从29K个晶体管到781M个晶体管&#xff0c;地址线&#xff08;也叫地址位长&#xff08;bit long))8086只有20个地址线&#xff0c;1982年&#xff0c;MS-windows 使用80286平台开发了自己的windows。直到1985年&#xff0c;i386正式扩展…

idea中 maven打包时时报错User setting file does not exist C:\Users\lenevo\.m2\setting.xml,

第一种错误 &#xff1a;idea中 maven打包时时报错User setting file does not exist C:\Users\lenevo\.m2\setting.xml&#xff0c; 解决方案如下&#xff1a;将maven的安装目录\conf目录下的setting.xml拷贝到C:\Users\lenevo\.m2目录下即可。 第二种错误&#xff1a; This a…

关于部署osd过程中:Device is in use by a device-mapper mapping问题解决

ceph环境&#xff1a;12.2.1 使用古老的ceph-disk工具部署osd,仅仅prepare过程中就出现如上所示问题 Device is in use by a device-mapper mapping md127 解决方法如下&#xff1a; 由于device-mapper为系统自己的磁盘映射器&#xff0c;此时检查系统是否有逻辑卷 pvs lvs vg…

spyder一打开就卡了_欧姆龙plc 用 SD 卡上传/下载程序

以Nx102为例&#xff0c;NJ类似。使用 SD 卡将 Sysmac Studio 编写的程序传入 NX1P2 内&#xff1b; 使用 SD 卡对NX1P2 的程序进行备份&#xff0c; 查看备份的程序&#xff0c; 并把备份的程序传入另一台对应型号的 NX1P2 内。一、 使用 SD 卡将 Sysmac Studio 写的程序传入 …

Unity3D 中 2D_Toolkit插件下载 和 导入方法

Unity3D 中 2D_Toolkit插件下载 和 导入方法 1.你把下载来的包放到 安装目录&#xff1a;Editor\Standard Packages里面。 2.然后按ctrl9&#xff0c;进入asset store&#xff0c;等页面加载。 3.页面加载成功后&#xff0c;如果有账号&#xff0c;就登录&#xff0c;没有账号先…

Emacs 使用YASnippet

<?xml version"1.0" encoding"utf-8"?> Emacs 使用YASnippetUP | HOME Emacs 使用YASnippet Table of Contents 1 安装YASnippent2 安装 org-mode字典3 org-mode中使用教程4 YASnippet增加模板1 安装YASnippent $ cd ~/.emacs.d/plugins $ git c…

ruoyi后台管理系统分析(三)---admin包

三、admin包 --web包 -----controller包 -----------common包 CommonController.java------通用请求处理 package com.ruoyi.web.controller.common;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest;…

ceph-objectstore-tool工具使用详解

文章目录简介使用OSD相关操作PG相关操作对象相关操作总结简介 ceph-objectstore-tool工具&#xff0c;能够操作到ceph最底层的数据&#xff0c;包括pg,对象层级。它能够对底层pg以及对象相关数据进行获取、修改。并能够对一些问题pg和对象进行简单修复。所以使用该工具进行操作…

slf4j导入那个依赖_学习SPRINGBOOT结合日志门面SLF4J和日志实现LOGBACK的混合使用

一、此处主要介绍在springboot工程下如何使用 logback slf4j 进行日志记录。logback主要包含三个组成部分&#xff1a;Loggers(日志记录器)、Appenders(输出目的在)、Layouts(日志输出格式) slf4j &#xff1a;如jdbc一样&#xff0c;定义了一套接口&#xff0c;是一个日志门面…

linux下发布的执行文件崩溃的问题定位 心得一则

C Release版本发布到客户处执行时&#xff0c;如果程序崩溃&#xff0c;有什么办法能够快速的确认程序的问题呢&#xff1f; 如果能gdb调试的话&#xff0c;比较简单了&#xff0c;可以使用gdb命令&#xff0c;类似如下&#xff1a;gdb ##set args ****b mainr#eipx/10i 0xb736…

7 个漂亮的 JavaScript 的时间轴组件 [转]

时间轴&#xff1a;通过互联网技术&#xff0c;依据时间顺序&#xff0c;把一方面或多方面的 时间足迹事件串联起来&#xff0c;形成相对完整的记录体系&#xff0c;再运用图文的形式呈现给用户&#xff1b;时间轴可以运用于不同领域&#xff0c;最大的作用就是把过去的事物系统…

Python 学习笔记: 反射

Python 反射应用 例子1&#xff1a; class Person:def __init__(self, name, age):self.name nameself.age agedef show(self):print(%s \s age is %s%(self.name, self.age))alex Person(alex, 18) # alex.show() if hasattr(alex, show):getattr(alex, show)() 转载于:ht…

C++多线程:互斥变量 std::mutex

文章目录描述成员函数总结描述 头文件 <mutex>使用 std::mutex <variable>简介 mutex是一种多线程变成中的同步原语&#xff0c;它能够让共享数据不被多个线程同时访问&#xff0c;它不支持递归得对互斥对象上锁特点 用方线程从它成功调用 lock 或 try_lock 开始&…

vim替换字符串带斜杠_Vim、gvim操作替换

~ 回复 以下关键词 查看更多IC设计教程 ~目前支持的关键词有&#xff1a;Innovus ICC or IC CompilerDC or Design Compiler PT or PrimeTimeUser Guide or UG LedaVCS Formality工艺节点 …

SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题...

转&#xff1a;http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据&#xff08;树形导航&#xff09;的webpart开发及问题 1、实现效果如下&#xff1a; 点击各个节点进入相应的链接 2、测试…

智能医疗?轻松实现!

每个中国人都及其关注养老和住房问题&#xff0c;在中国每个人都十分有存钱的意识。就目前来看&#xff0c;现在的医疗和住房保障还没有能够满足我们现在的需求&#xff0c;因而&#xff0c;存钱显得尤为重要。我们关注医疗&#xff0c;是因为每个人都会面临年老&#xff0c;每…

TokuDB vs Innodb 基准测试对比

随着业务的发展以及mysql存储数据量的越来越大&#xff0c;很多超大表不仅仅存储变的不易&#xff0c;维护也变得越来越困难&#xff0c;特别是频繁的ddl操作让运维变得痛苦不堪。当然表拆分可以解决类似的问题&#xff0c;但是对一个稳定的系统来说&#xff0c;表拆分对业务的…

C++ 多线程:互斥对象 lock_gurad

描述 头文件:<mutex>声明方式: template< class Mutex > class lock_guard;简介 lock_guard是一种互斥包装器&#xff0c;它提供了非常便捷的raii资源管控技术用来在对象生存周期内提供互斥锁。 lock_gurad很好得解决了互斥变量mutex的锁成员在函数异常期间无法正…

太TM难看了,我自己都看不下去了

继续研究文件IO。 作用是用System.in输入一个文件路径&#xff0c;然后打印文件里的所有行。 而且虽然没仔细检查过&#xff0c;哦不就是因为没检查过&#xff0c;所以肯定不够健壮。 1 import java.io.*;2 import java.util.Scanner;3 4 public class test {5 public stat…

儿童吹泡泡水简单配方_自制泡泡水最简单配方的做法教程

泡泡吸引着各个年龄段的人&#xff0c;就像是反射彩虹的表面&#xff0c;在微风中漂浮。无论您是出于什么原因&#xff0c;都很容易在其中找到快乐。吹泡泡可以让小孩玩上几个小时&#xff0c;而大一点的孩子可以尝试制作最佳泡泡液。对于年轻的萌芽科学家来说&#xff0c;制备…

Linux系统下统计目录及其子目录文件个数

改变脚本权限&#xff1a;(这里假设你的脚本叫FileCount.sh) chmod ax FileCount.sh 脚本&#xff1a; 1 #!/bin/sh 2 echo 查看某目录下文件的个数 3 ls -l |grep "^-"|wc -l 4 5 echo 查看某目录下文件的个数&#xff0c;包括子目录里的。 6 ls -lR|grep "^-…

【Rsync项目实战一】备份全网服务器数据

目录 【Rsync项目实战】备份全网服务器数据 【企业案例】1.1 环境部署1.2 开始部署backup服务器&#xff1a;Rsync服务端过程&#xff1a;1.3 开始部署nfs01服务器&#xff1a;Rsync客户端过程&#xff1a;【Rsync项目实战】备份全网服务器数据 标签&#xff08;空格分隔&#…