最近想做一个粒子沿轨迹线运动的东东,不过还是先实现了一个小目标,有空在添加粒子的部分。
功能:主要的功能如下,就是一个小球沿着一个随意生成的线运动。
原理:原理也不复杂,两个点之间的向量差就是小球应该运动的方向。直接加上小球当前的位置就是小球要到达的目标位置。
主要代码:默认为threeJS标准场景,参考:(留个坑,假装有连接)
先随机生成几个点存下来,我想让点都在坐标轴正方向的象限内,就取了随机数0-1的值,如果想让点存在于任意象限内,可以减去0.5
var points=[];
var pointsV3=[];
var point = new THREE.Vector3();
var direction = new THREE.Vector3();
for(var i =0; i < 8; i++)
{
direction.x = Math.random();
direction.y = Math.random();
direction.z = Math.random();
direction.normalize().multiplyScalar(30);
point.add(direction);
pointsV3.push(point.clone());
points.push(point.x,point.y,point.z);
}
根据随机点,生成一条线。用的是buffer格式的Geometry,所以,传进去的是一个float[]类型的数据,不是vector3[],这也是上面定义了 pointsV3 的原因, pointsV3 才是 vector3[] 类型的。
var lineGeometry = new THREE.BufferGeometry();
lineGeometry.addAttribute('position',new THREE.Float32BufferAttribute(points,3));
var line = new THREE.Line(lineGeometry, new THREE.LineBasicMaterial({
color:0x1e8cfc
}));
scene.add(line);
来一个小球,把小球的初始化位置放在第一个点的位置,这样方便观察它是不是老老实实的按照轨迹运行了。
material = new THREE.MeshStandardMaterial( {
color: 0xfabbc1,
metalness: 0.5,
roughness: 1.0,
flatShading: true
} );
sphere = new THREE.Mesh( new THREE.SphereBufferGeometry( 3, 20, 20), material );
sphere.position.set( 0, 0, 10 );
sphere.name = "Sphere";
scene.add( sphere );
sphere.position.set(pointsV3[0].x,pointsV3[0].y,pointsV3[0].z);
目标位置:这里面的clone很重要,我说我怎么算都不对捏,查了three源码才知道,如果不clone的话,会污染掉position数据本身,他就会跑到其他我们不想要的位置上去。
tweenpos= sphere.position.clone().add(pointsV3[index+1].clone().sub(pointsV3[index]));
运动的动画,使用的是Tween.js,相关地址:https://github.com/tweenjs/tween.js
其实我们只需要一个 Tween.js 的脚本引入到我们的工程里就可以了。
主要的的运动代码如下:创建一个tween,传入起始位置,结束位置,运动方式,以及update和complete的回调。complete 的回调里重新计算了要移动的目标位置,并重新创建了一个动画。
tween = new TWEEN.Tween(sphere.position.clone())
.to(tweenpos,3000)
.easing(TWEEN.Easing.Quadratic.InOut)
.delay(1000)
.onUpdate(function(){sphere.position.set(this.x, this.y,this.z);})
.onComplete(tweenComplete)
.start();
function tweenComplete()
{
if((index+1)<pointsV3.length)
{
index++;
tweenpos=sphere.position.clone().add(pointsV3[index+1].clone()
.sub(pointsV3[index]));
tween = new TWEEN.Tween(sphere.position.clone())
.to(tweenpos,3000)
.easing(TWEEN.Easing.Quadratic.InOut)
.delay(1000)
.onUpdate(function(){sphere.position.set(this.x, this.y,this.z);})
.onComplete(tweenComplete)
.start();
}
}
function animate(time) {
TWEEN.update(time);
}
以上就是这个小测试的主要代码。来来,给自己挖个坑,我会尽快测试一下,粒子沿线移动的功能看看效果如何。详见:(假装这里有个链接 = =)点我~~!