上一节中我们实现了物体沿指定轨迹移动的动画效果,这一节我们来实现让模型移动到鼠标点击的制定位置的动画效果。
先看下实现后的最终效果
要实现上面的动画效果,我们需要通过以下步骤来实现
第一步,监听鼠标事件
我们需要监听鼠标的点击事件,获取鼠标点击点相对浏览器可视区域左上角的距离,通过监听“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文章来源:https://www.toymoban.com/news/detail-484904.html
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、执行完成后清除定时器文章来源地址https://www.toymoban.com/news/detail-484904.html
到了这里,关于Threejs进阶之十:让模型移动到鼠标点击的指定位置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!