I discovered three.js which I love to use now, but I built a rotating car animation with keyboard arrows to control it, but I can't find out how to make a sliding animation (e.g.,
-> -> ->
) Instead of a rotation animation. I tried searching but I don't even know how to explain it other than a sliding animation. Does someone know how / if you can do this?
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ThreeJS Animation</title>
<style>
body {
margin: 0;
font-weight: 100;
float: none;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script src="https://threejs.org/build/three.js"></script>
<script>
let carBottomColor = "#999";
let carTopColor = "#FFF";
let carWindowColor = "#666";
const scene = new THREE.Scene();
scene.background = new THREE.Color("#f1f1f1");
const car = createCar();
scene.add(car);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(200, 500, 300);
scene.add(dirLight);
const aspectRatio = window.innerWidth / window.innerHeight;
const cameraWidth = 300;
const cameraHeight = cameraWidth / aspectRatio;
const camera = new THREE.OrthographicCamera(
cameraWidth / -2, // left
cameraWidth / 2, // right
cameraHeight / 2, // top
cameraHeight / -2, // bottom
200, // near plane
800 // far plane
);
camera.position.set(200, 200, 200);
camera.lookAt(0, 10, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
let x = 0;
let y = 0;
let keydown = '';
document.body.addEventListener('keydown', e => {
keydown = e.key;
});
document.body.addEventListener('keyup', e => {
keydown = '';
});
const update = () => {
switch (keydown) {
case 'ArrowUp':
x -= 0.1;
car.rotation.x = x;
break;
case 'ArrowDown':
x = 0.1;
car.rotation.x = x;
break;
case 'ArrowLeft':
y -= 0.1;
car.rotation.y = y;
break;
case 'ArrowRight':
y = 0.1;
car.rotation.y = y;
break;
}
window.requestAnimationFrame(update);
}
window.requestAnimationFrame(update);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
document.body.appendChild(renderer.domElement);
function createCar() {
const car = new THREE.Group();
const backWheel = createWheels();
backWheel.position.y = 6;
backWheel.position.x = -18;
car.add(backWheel);
const frontWheel = createWheels();
frontWheel.position.y = 6;
frontWheel.position.x = 18;
car.add(frontWheel);
const main = new THREE.Mesh(
new THREE.BoxBufferGeometry(60, 15, 30),
new THREE.MeshLambertMaterial({ color: carBottomColor })
);
main.position.y = 12;
car.add(main);
const carFrontTexture = getCarFrontTexture();
const carBackTexture = getCarFrontTexture();
const carRightSideTexture = getCarSideTexture();
const carLeftSideTexture = getCarSideTexture();
carLeftSideTexture.center = new THREE.Vector2(0.5, 0.5);
carLeftSideTexture.rotation = Math.PI;
carLeftSideTexture.flipY = false;
const cabin = new THREE.Mesh(new THREE.BoxBufferGeometry(33, 12, 24), [
new THREE.MeshLambertMaterial({ map: carFrontTexture }),
new THREE.MeshLambertMaterial({ map: carBackTexture }),
new THREE.MeshLambertMaterial({ color: carTopColor }), // top
new THREE.MeshLambertMaterial({ color: carTopColor }), // bottom
new THREE.MeshLambertMaterial({ map: carRightSideTexture }),
new THREE.MeshLambertMaterial({ map: carLeftSideTexture })
]);
cabin.position.x = -6;
cabin.position.y = 25.5;
car.add(cabin);
return car;
}
function createWheels() {
const geometry = new THREE.BoxBufferGeometry(12, 12, 33);
const material = new THREE.MeshLambertMaterial({ color: "#333" });
const wheel = new THREE.Mesh(geometry, material);
return wheel;
}
function getCarFrontTexture() {
const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 32;
const context = canvas.getContext("2d");
context.fillStyle = "#ffffff";
context.fillRect(0, 0, 64, 32);
context.fillStyle = carWindowColor || carBaseColor; // Wheel color
context.fillRect(8, 8, 48, 24);
return new THREE.CanvasTexture(canvas);
}
function getCarSideTexture() {
const canvas = document.createElement("canvas");
canvas.width = 128;
canvas.height = 32;
const context = canvas.getContext("2d");
context.fillStyle = "#ffffff";
context.fillRect(0, 0, 128, 32);
context.fillStyle = carWindowColor || carBaseColor; // Wheel color
context.fillRect(10, 8, 38, 24);
context.fillRect(58, 8, 60, 24);
return new THREE.CanvasTexture(canvas);
}
</script>
</body>
</html>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
I made some assumptions, but I think what you're trying to do is rotate the car along the y-axis when pressing left/right arrows, and you're trying to move the card forward when pressing up/down arrows. If that's the case, then you can do car.translateX()
to create that forward/backward motion, and car.rotation.y
to make the car turn.
Here's the modified example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ThreeJS Animation</title>
<style>
body {
margin: 0;
font-weight: 100;
float: none;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script src="https://threejs.org/build/three.js"></script>
<script>
let carBottomColor = "#999";
let carTopColor = "#FFF";
let carWindowColor = "#666";
const scene = new THREE.Scene();
scene.background = new THREE.Color("#f1f1f1");
const car = createCar();
scene.add(car);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(200, 500, 300);
scene.add(dirLight);
const aspectRatio = window.innerWidth / window.innerHeight;
const cameraWidth = 300;
const cameraHeight = cameraWidth / aspectRatio;
const camera = new THREE.OrthographicCamera(
cameraWidth / -2, // left
cameraWidth / 2, // right
cameraHeight / 2, // top
cameraHeight / -2, // bottom
200, // near plane
800 // far plane
);
camera.position.set(200, 200, 200);
camera.lookAt(0, 10, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
let x = 0;
let y = 0;
let keydown = '';
document.body.addEventListener('keydown', e => {
e.preventDefault();
keydown = e.key;
});
document.body.addEventListener('keyup', e => {
keydown = '';
});
const update = () => {
switch (keydown) {
case 'ArrowUp':
car.translateX(1.0);
break;
case 'ArrowDown':
car.translateX(-1.0);
break;
case 'ArrowLeft':
y = 0.1;
car.rotation.y = y;
break;
case 'ArrowRight':
y -= 0.1;
car.rotation.y = y;
break;
}
window.requestAnimationFrame(update);
}
window.requestAnimationFrame(update);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
document.body.appendChild(renderer.domElement);
function createCar() {
const car = new THREE.Group();
const backWheel = createWheels();
backWheel.position.y = 6;
backWheel.position.x = -18;
car.add(backWheel);
const frontWheel = createWheels();
frontWheel.position.y = 6;
frontWheel.position.x = 18;
car.add(frontWheel);
const main = new THREE.Mesh(
new THREE.BoxBufferGeometry(60, 15, 30),
new THREE.MeshLambertMaterial({ color: carBottomColor })
);
main.position.y = 12;
car.add(main);
const carFrontTexture = getCarFrontTexture();
const carBackTexture = getCarFrontTexture();
const carRightSideTexture = getCarSideTexture();
const carLeftSideTexture = getCarSideTexture();
carLeftSideTexture.center = new THREE.Vector2(0.5, 0.5);
carLeftSideTexture.rotation = Math.PI;
carLeftSideTexture.flipY = false;
const cabin = new THREE.Mesh(new THREE.BoxBufferGeometry(33, 12, 24), [
new THREE.MeshLambertMaterial({ map: carFrontTexture }),
new THREE.MeshLambertMaterial({ map: carBackTexture }),
new THREE.MeshLambertMaterial({ color: carTopColor }), // top
new THREE.MeshLambertMaterial({ color: carTopColor }), // bottom
new THREE.MeshLambertMaterial({ map: carRightSideTexture }),
new THREE.MeshLambertMaterial({ map: carLeftSideTexture })
]);
cabin.position.x = -6;
cabin.position.y = 25.5;
car.add(cabin);
return car;
}
function createWheels() {
const geometry = new THREE.BoxBufferGeometry(12, 12, 33);
const material = new THREE.MeshLambertMaterial({ color: "#333" });
const wheel = new THREE.Mesh(geometry, material);
return wheel;
}
function getCarFrontTexture() {
const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 32;
const context = canvas.getContext("2d");
context.fillStyle = "#ffffff";
context.fillRect(0, 0, 64, 32);
context.fillStyle = carWindowColor || carBaseColor; // Wheel color
context.fillRect(8, 8, 48, 24);
return new THREE.CanvasTexture(canvas);
}
function getCarSideTexture() {
const canvas = document.createElement("canvas");
canvas.width = 128;
canvas.height = 32;
const context = canvas.getContext("2d");
context.fillStyle = "#ffffff";
context.fillRect(0, 0, 128, 32);
context.fillStyle = carWindowColor || carBaseColor; // Wheel color
context.fillRect(10, 8, 38, 24);
context.fillRect(58, 8, 60, 24);
return new THREE.CanvasTexture(canvas);
}
</script>
</body>
</html>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>