-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathanimation_tween.html
160 lines (141 loc) · 5.64 KB
/
animation_tween.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<!DOCTYPE html>
<html>
<head>
<title>Particle Trajectory Animation with Multiple Tracks</title>
<style>
body { margin: 0; }
canvas { display: block; }
#controls { position: absolute; top: 10px; left: 10px; z-index: 100; }
</style>
</head>
<body>
<div id="controls">
<input type="range" id="timeSlider" min="0" max="9000" step="10" value="0" />
</div>
<script type="module">
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js';
import { TWEEN } from 'https://unpkg.com/@tweenjs/[email protected]/dist/tween.esm.js';
// Set up the scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create spheres to represent the particles
const geometry = new THREE.SphereGeometry(0.1, 32, 32);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const particle1 = new THREE.Mesh(geometry, material);
const particle2 = new THREE.Mesh(geometry, material);
particle1.visible = false; // Initially invisible
particle2.visible = false; // Initially invisible
scene.add(particle1);
scene.add(particle2);
// Position the camera
camera.position.z = 5;
// Define the trajectories with points and timestamps
const trajectories = [
[
{ x: 0, y: 0, z: 0, time: 1000 },
{ x: 1, y: 1, z: 0, time: 2000 },
{ x: 2, y: 0, z: 1, time: 3000 },
{ x: 3, y: -1, z: 0, time: 4000 },
{ x: 4, y: 0, z: -1, time: 5000 }
],
[
{ x: 4, y: 0, z: -1, time: 5000 },
{ x: 5, y: 1, z: -1, time: 6000 },
{ x: 6, y: 2, z: 0, time: 7000 },
{ x: 7, y: 1, z: 1, time: 8000 },
{ x: 8, y: 0, z: 1, time: 9000 }
],
[
{ x: 8, y: 0, z: 1, time: 5000 },
{ x: 9, y: -1, z: 1, time: 6000 },
{ x: 10, y: -2, z: 0, time: 7000 },
{ x: 11, y: -1, z: -1, time: 8000 },
{ x: 12, y: 0, z: -1, time: 9000 }
]
];
// Create splines for each trajectory
const curves = trajectories.map(points => {
return new THREE.CatmullRomCurve3(points.map(p => new THREE.Vector3(p.x, p.y, p.z)));
});
// Create full line geometries for each trajectory
const lines = curves.map(curve => {
const linePoints = curve.getPoints(100);
const lineGeometry = new THREE.BufferGeometry().setFromPoints(linePoints);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0x0000ff });
const line = new THREE.Line(lineGeometry, lineMaterial);
line.visible = false; // Initially invisible
scene.add(line);
return line;
});
// Get the time slider element
const timeSlider = document.getElementById('timeSlider');
// Function to update the particles' positions and line visibility based on the current time
function updateParticlePosition(currentTime) {
const delay = 1000; // Delay before the particles appear
if (currentTime < delay) {
particle1.visible = false;
particle2.visible = false;
lines.forEach(line => line.visible = false);
return;
}
particle1.visible = true;
particle2.visible = currentTime >= 5000;
let adjustedTime = currentTime - delay;
// Track 1
if (adjustedTime <= 4000) {
lines[0].visible = true;
const t1 = adjustedTime / 4000;
const position1 = curves[0].getPoint(t1);
particle1.position.copy(position1);
const visiblePoints1 = curves[0].getPoints(Math.floor(t1 * 100) + 1);
lines[0].geometry.setFromPoints(visiblePoints1);
}
// Track 2
if (adjustedTime >= 4000 && adjustedTime <= 8000) {
lines[1].visible = true;
const t2 = (adjustedTime - 4000) / 4000;
const position2 = curves[1].getPoint(t2);
particle1.position.copy(position2);
const visiblePoints2 = curves[1].getPoints(Math.floor(t2 * 100) + 1);
lines[1].geometry.setFromPoints(visiblePoints2);
}
// Track 3 (second particle)
if (adjustedTime >= 4000 && adjustedTime <= 8000) {
lines[2].visible = true;
const t3 = (adjustedTime - 4000) / 4000;
const position3 = curves[2].getPoint(t3);
particle2.position.copy(position3);
const visiblePoints3 = curves[2].getPoints(Math.floor(t3 * 100) + 1);
lines[2].geometry.setFromPoints(visiblePoints3);
}
}
// Event listener for the time slider
timeSlider.addEventListener('input', (event) => {
const currentTime = parseInt(event.target.value, 10);
updateParticlePosition(currentTime);
});
// Function to control the tweens and set the state at a specific time t0
function setAnimationTime(t0) {
timeSlider.value = t0;
updateParticlePosition(t0);
}
// Add event listener to the slider for manual control
timeSlider.addEventListener('change', (event) => {
const currentTime = parseInt(event.target.value, 10);
setAnimationTime(currentTime);
});
// Initial update
updateParticlePosition(timeSlider.value);
// Animation loop
function animate() {
requestAnimationFrame(animate);
TWEEN.update();
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>