英文:
Web animation speeds up with each use
问题
以下是您要翻译的代码部分:
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
document.addEventListener('keydown', onDocumentKeyDown, false);
document.addEventListener('keyup', onDocumentKeyUp, false);
function onDocumentKeyDown(event) {
event = event || window.event;
var keycode = event.keyCode;
switch (keycode) {
case 38:
tb -= 5;
break;
case 40:
tb += 5;
break;
case 37:
t -= 5;
break;
case 39:
t += 5;
break;
}
}
function onDocumentKeyUp(event) {
event = event || window.event;
var keycode = event.keyCode;
requestAnimationFrame(render);
cube.position.x += 0 * Math.sin(t);
renderer.render(scene, camera);
switch (keycode) {
case 37:
console.log("left up");
break;
case 38:
console.log("up up");
break;
case 39:
console.log("right up");
break;
case 40:
console.log("down up");
break;
}
}
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, 0.1, 10000);
camera.position.z = 50;
scene.add(camera);
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
var phongMaterial = new THREE.MeshPhongMaterial({
color: 0xFF0000
});
var cube = new THREE.Mesh(boxGeometry, phongMaterial);
cube.position.x = -25;
cube.rotation.set(0.4, 0.2, 1);
scene.add(cube);
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(-10, 15, 50);
scene.add(light);
var t = 0;
var tb = 0;
function render() {
if (t > 0) t *= 0.98;
if (t < 0) t *= 0.98;
if (t > 0 && t < 0.5) t = 0;
if (t < 0 && t > (-0.5)) t = 0;
if (tb > 0) tb *= 0.98;
if (tb < 0) tb *= 0.98;
if (tb > 0 && tb < 0.5) tb = 0;
if (tb < 0 && tb > (-0.5)) tb = 0;
requestAnimationFrame(render);
if (t != 0) console.log(t);
cube.position.x += 0.1 * t;
cube.position.z += 0.1 * tb;
renderer.render(scene, camera);
}
render();
这是您的代码部分的翻译。
英文:
For an exercise, I'm supposed to create a book that's controlled by the arrow keys and smoothly stops when no keys are held. However, every time I click an arrow key, the animation plays faster and faster.
I'll paste the code below, sorry for not limiting it to the necessary part, but I don't fully comprehend it myself.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
document.addEventListener('keydown', onDocumentKeyDown, false);
document.addEventListener('keyup', onDocumentKeyUp, false);
function onDocumentKeyDown(event) {
event = event || window.event;
var keycode = event.keyCode;
switch (keycode) {
case 38:
tb -= 5;
break;
case 40:
tb += 5;
break;
case 37:
t -= 5;
break;
case 39:
t += 5;
break;
}
}
function onDocumentKeyUp(event) {
event = event || window.event;
var keycode = event.keyCode;
requestAnimationFrame(render);
cube.position.x += 0 * Math.sin(t);
renderer.render(scene, camera);
switch (keycode) {
case 37:
console.log("left up");
break;
case 38:
console.log("up up");
break;
case 39:
console.log("right up");
break;
case 40:
console.log("down up");
break;
}
}
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, 0.1, 10000);
camera.position.z = 50;
scene.add(camera);
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
var phongMaterial = new THREE.MeshPhongMaterial({
color: 0xFF0000
});
var cube = new THREE.Mesh(boxGeometry, phongMaterial);
cube.position.x = -25;
cube.rotation.set(0.4, 0.2, 1);
scene.add(cube);
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(-10, 15, 50);
scene.add(light);
var t = 0;
var tb = 0;
function render() {
if (t > 0) t *= 0.98;
if (t < 0) t *= 0.98;
if (t > 0 && t < 0.5) t = 0;
if (t < 0 && t > (-0.5)) t = 0;
if (tb > 0) tb *= 0.98;
if (tb < 0) tb *= 0.98;
if (tb > 0 && tb < 0.5) tb = 0;
if (tb < 0 && tb > (-0.5)) tb = 0;
requestAnimationFrame(render);
if (t != 0) console.log(t);
cube.position.x += 0.1 * t;
cube.position.z += 0.1 * tb;
renderer.render(scene, camera);
}
render();
<!-- language: lang-css -->
body {
margin: 0;
padding: 0;
font-size: 0;
}
canvas {
width: 100%;
height: 100%;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<!-- end snippet -->
答案1
得分: 3
从键盘监听器中删除requestAnimationFrame(render)
。render
函数已经在循环中运行,因此再次调用它会导致多个版本的函数同时运行。同样适用于调用renderer.render(scene, camera);
,这应该只在一个地方调用。
提示:在键盘监听器中更新t
/tb
(这些变量名可能需要更清晰的名称...)会在按键重新触发时导致不寻常的行为。为了更可预测和平滑的键盘操作,让键盘监听器仅翻转每个键的布尔值,并让渲染循环处理对t
和tb
的更改。
另一个一般性建议是避免在渲染循环中硬编码数值。这样做的问题是原始值没有语义意义,随着代码的增长,它变得容易出错且难以更改。理想情况下,创建一个配置对象,将这些值存储在一个地方,并使用适当的名称(例如acceleration
、damping
等)。
以下是代码部分的翻译:
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var keyMap = { 37: "l", 38: "u", 39: "r", 40: "d" };
var keys = {};
document.addEventListener("keydown", function (e) {
e = e || window.event;
keys[keyMap[e.keyCode]] = true;
}, false);
document.addEventListener("keyup", function (e) {
e = e || window.event;
keys[keyMap[e.keyCode]] = false;
}, false);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, 0.1, 10000);
camera.position.z = 50;
scene.add(camera);
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
var phongMaterial = new THREE.MeshPhongMaterial({
color: 0xFF0000
});
var cube = new THREE.Mesh(boxGeometry, phongMaterial);
cube.position.x = -25;
cube.rotation.set(0.4, 0.2, 1);
scene.add(cube);
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(-10, 15, 50);
scene.add(light);
var t = 0;
var tb = 0;
function render() {
if (keys.u) tb -= 5;
if (keys.d) tb += 5;
if (keys.r) t += 5;
if (keys.l) t -= 5;
if (t > 0) t *= 0.98;
if (t < 0) t *= 0.98;
if (t > 0 && t < 0.5) t = 0;
if (t < 0 && t > (-0.5)) t = 0;
if (tb > 0) tb *= 0.98;
if (tb < 0) tb *= 0.98;
if (tb > 0 && tb < 0.5) tb = 0;
if (tb < 0 && tb > (-0.5)) tb = 0;
cube.position.x += 0.1 * t;
cube.position.z += 0.1 * tb;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
希望这能帮助您理解代码的一部分!
英文:
Remove requestAnimationFrame(render)
from the key listener. The render
function is already running in a loop, so calling it again causes multiple versions of the function to run at the same time. Same goes for calling renderer.render(scene, camera);
--this should be called in one place only.
Tip: updating t
/tb
(these var names could be clearer...) inside the key listener causes unusual behavior when the key retriggers. For more predictable and smooth keyboard action, have the key listeners simply flip booleans for each key on and off and let the rendering loop handle the change to t
and tb
.
Another general suggestion is to avoid hardcoded values inside your rendering loop. The problem with this is the raw values have no semantic meaning and it becomes error-prone and difficult to change them as the code grows. Ideally, create a configuration object that stores these values in one place with appropriate names (acceleration
, damping
, etc). I'll leave that as an exercise.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var keyMap = {37: "l", 38: "u", 39: "r", 40: "d"};
var keys = {};
document.addEventListener("keydown", function (e) {
e = e || window.event;
keys[keyMap[e.keyCode]] = true;
}, false);
document.addEventListener("keyup", function (e) {
e = e || window.event;
keys[keyMap[e.keyCode]] = false;
}, false);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, 0.1, 10000);
camera.position.z = 50;
scene.add(camera);
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
var phongMaterial = new THREE.MeshPhongMaterial({
color: 0xFF0000
});
var cube = new THREE.Mesh(boxGeometry, phongMaterial);
cube.position.x = -25;
cube.rotation.set(0.4, 0.2, 1);
scene.add(cube);
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(-10, 15, 50);
scene.add(light);
var t = 0;
var tb = 0;
function render() {
if (keys.u) tb -= 5;
if (keys.d) tb += 5;
if (keys.r) t += 5;
if (keys.l) t -= 5;
if (t > 0) t *= 0.98;
if (t < 0) t *= 0.98;
if (t > 0 && t < 0.5) t = 0;
if (t < 0 && t > (-0.5)) t = 0;
if (tb > 0) tb *= 0.98;
if (tb < 0) tb *= 0.98;
if (tb > 0 && tb < 0.5) tb = 0;
if (tb < 0 && tb > (-0.5)) tb = 0;
cube.position.x += 0.1 * t;
cube.position.z += 0.1 * tb;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
<!-- language: lang-css -->
body {
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论