我使用three.js编写了一个小的动画函数用于3D渲染(下面的完整测试应用程序):
每次我点击屏幕时,立方体都会根据函数调用中描述的动画进行旋转。但我期待如果立方体已经在一个动画下动画,则添加另一个会导致它闪烁,因为相同的属性被多个动画调用动画化。但这并不是最后一个动画停止并且新动画接管的情况,即使我最后的回调函数显示旧的动画功能仍在运行!那么为什么多维数据集发送时多维数据集不会闪烁?
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
<script src="three-mini.js"></script>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script>
var animate = function(obj, prop, targetValue, length, callback) {
var startTime = Date.now(), inverseLength = 1 / length, startValue = obj[prop];
if( typeof targetValue === "string") {
if(targetValue.substring(0, 2) === "+=") {
targetValue = obj[prop] + Number(targetValue.substring(2));
} else {
targetValue = obj[prop] - Number(targetValue.substring(2));
}
}
var animateProp = function() {
var elapsed = (Date.now() - startTime) * inverseLength;
if(elapsed >= 1) {
obj[prop] = targetValue;
if( callback instanceof Function) {
requestAnimationFrame(callback);
}
return;
} else {
obj[prop] = (startValue - targetValue) * (Math.cos(elapsed * Math.PI) + 1) * 0.5 + targetValue;
requestAnimationFrame(animateProp);
}
};
requestAnimationFrame(animateProp);
};
var camera, scene, renderer;
var geometry, material, mesh;
init();
function init() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
scene = new THREE.Scene();
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshBasicMaterial({
color : 0xff0000,
wireframe : true
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.domElement.addEventListener('click', function() {
animate(mesh.rotation, "x", "-=" + Math.PI * 2 * 10, 5000, function() {
alert("CALLED BACK!")
});
animate(mesh.rotation, "y", "-=" + Math.PI * 2 * 10, 15000, function() {
});
});
window.addEventListener('load', render);
window.addEventListener('resize', function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
}
function render() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame(render);
renderer.render(scene, camera);
}
</script>
</body>
</html>
更新1:
为了找出发生了什么,我添加了更多网格并将它们全部设置为不同,代码如下,它为每个后续点击动画每个网格,然后通过旋转动画它们然后向前移动它们然后向后移动,然后回到轮换。您可以在不停止旋转动画的情况下为位置设置动画,并且可以在不停止先前动画的情况下同时为一个网格设置动画,而不停止以前的动画,因此当多个动画在同一网格上运行并且在相同属性上时,为什么动画不会闪烁?
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
<script src="three-mini.js"></script>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script>
var animate = function(obj, prop, targetValue, length, callback) {
var startTime = Date.now(), inverseLength = 1 / length, startValue = obj[prop];
if( typeof targetValue === "string") {
if(targetValue.substring(0, 2) === "+=") {
targetValue = obj[prop] + Number(targetValue.substring(2));
} else {
targetValue = obj[prop] - Number(targetValue.substring(2));
}
}
var animateProp = function() {
var elapsed = (Date.now() - startTime) * inverseLength;
if(elapsed >= 1) {
obj[prop] = targetValue;
if( callback instanceof Function) {
requestAnimationFrame(callback);
}
return;
} else {
obj[prop] = (startValue - targetValue) * (Math.cos(elapsed * Math.PI) + 1) * 0.5 + targetValue;
requestAnimationFrame(animateProp);
}
};
requestAnimationFrame(animateProp);
};
var camera, scene, renderer, geometry, material, mesh1, mesh2, mesh3, mesh4, mesh5, i = 0, j = 0;
init();
function init() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
scene = new THREE.Scene();
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshBasicMaterial({
color : 0xff0000,
wireframe : true
});
mesh1 = new THREE.Mesh(geometry, material);
scene.add(mesh1);
mesh2 = new THREE.Mesh(geometry, material);
mesh2.position.x = mesh2.position.y = mesh2.position.z = 200;
scene.add(mesh2);
mesh3 = new THREE.Mesh(geometry, material);
mesh3.position.x = mesh3.position.z = 200;
mesh3.position.y = -200;
scene.add(mesh3);
mesh4 = new THREE.Mesh(geometry, material);
mesh4.position.y = mesh4.position.z = 200;
mesh4.position.x = -200;
scene.add(mesh4);
mesh5 = new THREE.Mesh(geometry, material);
mesh5.position.y = mesh5.position.x = -200;
mesh5.position.z = 200;
scene.add(mesh5);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.domElement.addEventListener('click', function() {
var mesh;
if(i === 5) {
i = 0;
j++;
if(j === 3) {
j = 0;
}
}
i++;
var mesh = window['mesh' + i];
if(j === 1) {
animate(mesh.position, "z", "+=" + 500, 2000, function() {
//alert("CALLED BACK!")
});
return;
}
if(j === 2) {
animate(mesh.position, "z", "-=" + 500, 3000, function() {
//alert("CALLED BACK!")
}); retunr;
}
animate(mesh.rotation, "x", "-=" + Math.PI * 2 * 5, 5000, function() {
//alert("CALLED BACK!")
});
animate(mesh.rotation, "y", "-=" + Math.PI * 2 * 6, 10000, function() {
});
});
window.addEventListener('load', render);
window.addEventListener('resize', function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
}
function render() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame(render);
renderer.render(scene, camera);
}
</script>
</body>
</html>
对WestLangley的评论:
让我试着解释一下,我为不清楚而道歉。假设我点击一次,它就会启动从position.x = 0
到targetValue: '+=200'
的动画。然后我再次点击该动画,然后再次点击这个动画在负x方向上动画,该方向将以position.x = 100
开始(因为它是从第一个动画的中途开始)并且有targetValue: '-=200'
。现在我希望第一个动画仍然在运行,因此它会继续从x=100
动画到x=200
,第二个动画现在也从x=100
运行到x=-100
,因此,当每个动画函数被调用时,我希望看到立方体左右跳跃,直到第一个动画结束,然后第二个动画可以不受阻碍地继续。这是我期待发生的事情,因此我期待它闪烁。但显然多个动画功能同时运行,但只有最新的功能才能更新网格属性。 :至少就我所说的而言。
我主要担心的是,我可以从实验中看出“隐藏的”动画调用仍在处理中,因此抛弃了宝贵的处理器周期,这也导致在回调函数中添加动画调用的问题。为此我主要担心的是如何停止这些“隐藏”的动画调用?
答案 0 :(得分:0)
我仍然不完全确定发生了什么,但我所知道的是,即使前面的动画没有显示,多个动画也在同一时间运行。我对此的主要担心是它正在消耗不必要的处理能力。所以我添加了后缀表示法,现在我将动画函数添加到动画属性拥有对象本身,所以如果我动画position.x
我创建我的动画函数并将其分配给position.x_animate
和{{ 1}}或者。这是我可以取消之前仍在运行的动画,所以我不会浪费处理器周期。仅针对下面的动画功能的完整代码段:
position.x_animate_alt