我正在Three.js中制作一个简单的多维数据集动画,但我被困住了。如何使动画到达1
时停止播放,然后以另一种方式反复播放-1
。
"use strict";
var scene = new THREE.Scene();
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);
renderer.setClearColor(0x404040, 1);
document.body.appendChild(renderer.domElement);
var clock = new THREE.Clock();
clock.start();
var t = 0;
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshPhongMaterial({
color: 0x008080,
specular: 0xffffff,
});
var cube = new THREE.Mesh(geometry, material);
var light = new THREE.PointLight(0xffffff, 6, 40);
var alight = new THREE.AmbientLight(0xffffff);
scene.add(alight);
light.position.set(20, 20, 20);
scene.add(light);
cube.add(createAxes(1));
scene.add(cube);
scene.add(createAxes(5));
renderer.render(scene, camera);
var controls = new THREE.TrackballControls(camera);
controls.addEventListener('change', render);
animate();
function render() {
renderer.render(scene, camera);
}
function animate() {
var dt = clock.getDelta();
t += dt;
var v = THREE.Math.lerp(-1, 1, t);
cube.position.x = v;
render();
requestAnimationFrame(animate);
controls.update();
}
我尝试在animate()
中使用循环来更改v
或1
时的-1
:
var v = THREE.Math.lerp(-1, 1, t);
if (v > 1) {
v = THREE.Math.lerp(1, -1, t);
}
if (v < -1) {
clock.stop();
}
cube.position.x = v;
我只想让多维数据集来回摆动,但它会平稳地转到1
,并立即压缩到-1
。任何回答都将不胜感激。
答案 0 :(得分:0)
最简单的解决方案是(如评论中所述)使用Math.sin()
:
cube.position.x = Math.sin(t);
但是,如果要实现从开始到结束再到向后的线性插值,则必须在当前相对位置(dir
)旁边定义当前方向(t
)。 :
var t = 0, dir = 1;
根据当前方向和.clamp
到[0,1]范围的位置来计算新的相对位置:
var new_t = t + dt * dir;
t = THREE.Math.clamp(new_t, 0, 1);
当相对位置超出限制时,更改方向:
if (t != new_t)
dir *= -1
功能animate
:
function animate() {
var dt = clock.getDelta();
var new_t = t + dt * dir;
t = THREE.Math.clamp(new_t, 0, 1);
if (t != new_t)
dir *= -1
var v = THREE.Math.lerp(-1, 1, t);
cube.position.x = v;
// [...]
}
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x404040, 1);
document.body.appendChild(renderer.domElement);
var clock = new THREE.Clock();
clock.start();
var t = 0, dir = 1;
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshPhongMaterial({
color: 0x008080,
specular: 0xffffff,
});
var cube = new THREE.Mesh(geometry, material);
var light = new THREE.PointLight(0xffffff, 6, 40);
var alight = new THREE.AmbientLight(0xffffff);
light.position.set(20, 20, 20);
scene.add(alight);
scene.add(light);
cube.add(new THREE.AxesHelper());
scene.add(cube);
scene.add(new THREE.AxesHelper());
renderer.render(scene, camera);
var controls = new THREE.TrackballControls(camera);
controls.addEventListener('change', render);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
animate();
function render() {
renderer.render(scene, camera);
}
function animate() {
var dt = clock.getDelta();
var new_t = t + dt * dir;
t = THREE.Math.clamp(new_t, 0, 1);
if (t != new_t)
dir *= -1
var v = THREE.Math.lerp(-1, 1, t);
cube.position.x = v;
//cube.position.x = Math.sin(t);
render();
requestAnimationFrame(animate);
controls.update();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>