Threejs进阶之十:让模型移动到鼠标点击的指定位置

上一节中我们实现了物体沿指定轨迹移动的动画效果,这一节我们来实现让模型移动到鼠标点击的制定位置的动画效果。
先看下实现后的最终效果
在这里插入图片描述
要实现上面的动画效果,我们需要通过以下步骤来实现

第一步,监听鼠标事件

我们需要监听鼠标的点击事件,获取鼠标点击点相对浏览器可视区域左上角的距离,通过监听“pointerdown”事件,获取点击点的clientX和clientY;clientX/Y获取到的是点击点相对浏览器可视区域左上角距离。

renderer.domElement.addEventListener('pointerdown',function(event) {
   
    event = event || window.event
    initPos = {
   
      x:event.clientX,
      y:event.clientY
    } 
})

第二步:获取鼠标点击点的屏幕坐标

通过Element.getBoundingClientRect()中的 top属性获取元素上边距离页面上边的距离,
通过left属性获取元素左边距离页面左边的距离,
通过计算 clientX 与domElement.getBoundingClientRect().left的差值,获取x点坐标;
通过计算 clientY 与domElement.getBoundingClientRect().top的差值,获取y点坐标;

  let x = event.clientX - renderer.domElement.getBoundingClientRect().left
  let y = event.clientY - renderer.domElement.getBoundingClientRect().top

第三步:获取画布的宽度和高度并归一化

通过坐标转换,将x和y的坐标归一化,即将屏幕坐标转换为threejs的世界坐标

 let canvasWidth = renderer.domElement.clientWidth 
 // clientWidth 返回元素的可视宽度,包括内边距,但不包括边框、滚动条或外边距,以像素计
 // canvas画布高度
 // clientHeight 返回元素的可视高度,包括内边距,但不包括边框、滚动条或外边距,以像素计。
 let canvasHeight = renderer.domElement.clientHeight
 // offsetHeight 属性返回元素的可视高度(以像素为单位),包括内边距、边框和滚动条,但不包括外边距。
 // offsetWidth 属性返回元素的可视宽度(以像素为单位),包括内边距、边框和滚动条,但不包括外边距。
 // 坐标转换(归一化的值) 
 const sx = -1 + (x / canvasWidth) * 2 
 const sy = 1 - (y / canvasHeight) * 2

第四步:创建光线投射器,并通过摄像机和鼠标点击的位置更新射线

// 光线投射器
const rayCaster = new THREE.Raycaster()
// 通过摄像机和鼠标位置更新射线
rayCaster.setFromCamera(new THREE.Vector2(sx,sy),camera) 

第五步:通过rayCaster.intersectObjects()方法检测射线与物体的交集

这里我们是点击在水面上,因此,将water作为参数传入,检测射线与水面的交集,将结果返回给intersects

const intersects = rayCaster.intersectObjects([water]) 

第六步:判断射线与物体是否有交集,如果有,获取坐标并处理逻辑

通过if语句判断intersects.length是否大于零,如果大于零,说明有交集,在if语句中处理如下逻辑:
1、通过intersects[0].point获取鼠标点击时射线与water相交点的坐标(新位置)存入newPos变量,
2、通过yacht.position.clone() 获取模型当前位置坐标(老位置)存入originPos变量
3、通过camera.position.clone() 获取相机当前位置坐标(老位置)存入cameraOriginPos 变量
4、通过向量减法获取鼠标点击点的向量和向量长度 存入vector 变量
5、创建一个四元数对象,通过.setFromUnitVectors将该四元数设置为从方向向量new THREE.Vector3(0,0,-1)旋转到方向向量 vector 单位向量 所需的旋转角度。
6、创建一个Threejs的Clock()对象
7、创建一个speed常量为100,设置移动速度
8、通过setInterval()方法启动定时器,通过speed和clock.getElapsedTime()失去时间的乘积,得到每次时间间隔移动的长度
9、通过每次时间间隔移动的长度除以向量总长度,获取每次间隔移动的比值,将该比值与重点向量相乘,得到每次间隔移动的向量坐标
10、将上面得到的每次间隔移动的向量坐标与模型原始位置向量坐标相加,得到模型每次时间间隔移动的重点向量坐标
11、将每次间隔移动的终点坐标复制给模型的position属性
12、将每次间隔移动的向量坐标与相机原始坐标相加得到每次时间间隔移动的终点坐标,并将给坐标复制给相机的position属性
13、将每次时间间隔的终点坐标movePos复制给控制器的target属性,使其始终朝向movePos位置
14、执行完成后清除定时器


                
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用Three.js可以轻松实现鼠标点击位置移动的效果。首先,在场景中创建一个3D模型,比如一个立方体或者球体。然后,监听鼠标点击事件,当鼠标模型上被点击时,获取点击位置的坐标。接着,可以通过修改模型位置,将模型移动鼠标点击位置。 具体的代码可以如下: ```javascript // 创建场景 var scene = new THREE.Scene(); // 创建一个立方体 var geometry = new THREE.BoxGeometry(1, 1, 1); var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); var cube = new THREE.Mesh(geometry, material); scene.add(cube); // 创建摄像机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; // 创建渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 监听鼠标点击事件 document.addEventListener('click', onDocumentMouseClick, false); function onDocumentMouseClick(event) { // 获取鼠标点击位置的坐标 var mouse = new THREE.Vector2(); mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; // 通过鼠标点击位置的坐标获取模型位置 var raycaster = new THREE.Raycaster(); raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObjects(scene.children); if (intersects.length > 0) { // 将模型移动鼠标点击位置 var targetPosition = intersects[0].point; cube.position.copy(targetPosition); } } // 渲染场景 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate(); ``` 以上代码通过监听鼠标点击事件,获取鼠标点击位置的坐标,并将模型移动到该位置。这样,就实现了鼠标点击位置移动的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九仞山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值