Skip to content

Commit

Permalink
Implement click trajectory animation
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaOrson committed Dec 27, 2024
1 parent 2f7a631 commit ec38f29
Showing 1 changed file with 63 additions and 5 deletions.
68 changes: 63 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<script lang="ts">
// Cleanup on unmount or k changes
import { onDestroy } from 'svelte';
// Types
type Point = [number, number]; // [theta, p]
type Trajectory = Point[];
Expand All @@ -17,6 +20,8 @@
let k = $state(0.7);
let trajectories = $state<Trajectory[]>([]);
let clickTrajectory = $state<Trajectory | null>(null);
let animationPoints = $state(0);
let animationInterval: number | null = null;
// Colors for trajectories
const colors = Array(NUM_TRAJECTORIES)
Expand Down Expand Up @@ -52,12 +57,13 @@
function generateTrajectory(
initialTheta: number,
initialP: number
initialP: number,
points = POINTS_PER_TRAJECTORY,
): Trajectory {
const trajectory: Trajectory = [];
let [theta, p] = [initialTheta, initialP];
for (let i = 0; i < POINTS_PER_TRAJECTORY; i++) {
for (let i = 0; i < points; i++) {
trajectory.push([theta, p]);
[theta, p] = nextState(theta, p);
}
Expand All @@ -75,6 +81,26 @@
});
}
function startTrajectoryAnimation(trajectory: Trajectory) {
// Clear any existing animation
if (animationInterval) {
clearInterval(animationInterval);
}
// Reset animation state
animationPoints = 0;
clickTrajectory = trajectory;
// Start animation
animationInterval = setInterval(() => {
if (animationPoints >= trajectory.length - 1) {
clearInterval(animationInterval!);
} else {
animationPoints++;
}
}, 20); // Adjust this value to control animation speed (20ms = 50fps)
}
function handleCanvasClick(event: MouseEvent | KeyboardEvent) {
if (event instanceof MouseEvent) {
const svg = document.querySelector('.phase-space') as SVGGraphicsElement;
Expand All @@ -92,7 +118,7 @@
const theta = ((svgPoint.x - MARGIN) / (WIDTH - 2 * MARGIN)) * TWO_PI;
const p = ((HEIGHT - svgPoint.y - MARGIN) / (HEIGHT - 2 * MARGIN)) * TWO_PI - PI;
clickTrajectory = generateTrajectory(theta, p);
startTrajectoryAnimation(generateTrajectory(theta, p, 10 * POINTS_PER_TRAJECTORY));
}
} else if (event instanceof KeyboardEvent) {
// Handle keyboard event
Expand All @@ -118,6 +144,12 @@
// Clear click trajectory when k changes
clickTrajectory = null;
});
onDestroy(() => {
if (animationInterval) {
clearInterval(animationInterval);
}
});
</script>

<div class="kicked-rotor">
Expand Down Expand Up @@ -231,9 +263,15 @@
<!-- Click Trajectory -->
{#if clickTrajectory}
<g class="click-trajectory">
{#each clickTrajectory as [theta, p]}
{#each clickTrajectory.slice(0, animationPoints + 1) as [theta, p], i}
{@const [x, y] = toSVGCoords(theta, p)}
<circle cx={x} cy={y} r="1.5" />
<circle
cx={x}
cy={y}
r="1.5"
class="animated-point"
style="--point-index: {i}"
/>
{/each}
</g>
{/if}
Expand Down Expand Up @@ -346,6 +384,26 @@
r: clamp(0.75px, 0.3vw, 1.5px);
}
.animated-point {
animation: pointAppear 0.3s ease-out forwards;
opacity: 0;
}
@keyframes pointAppear {
from {
opacity: 0;
r: 0.5;
}
50% {
opacity: 1;
r: 2.5;
}
to {
opacity: 0.8;
r: 1.5;
}
}
.controls {
margin: 0.5rem 0;
display: flex;
Expand Down

0 comments on commit ec38f29

Please sign in to comment.