Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

May the best easing win

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
/** @jsxImportSource https://esm.sh/react */
import React, { useState, useEffect } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
import { BrowserRouter as Router, Route, Link, Routes } from "https://esm.sh/react-router-dom";
function EasingVisualizer({ easing }) {
const canvasRef = React.useRef(null);
React.useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
function drawCurve() {
ctx.clearRect(0, 0, width, height);
const [x1, y1, x2, y2] = easing.params;
const bezierFunction = cubicBezier(x1, y1, x2, y2);
ctx.beginPath();
ctx.moveTo(0, height);
for (let t = 0; t <= 1; t += 0.01) {
const point = bezierFunction(t);
const x = point.x * width;
const y = height - point.y * height;
ctx.lineTo(x, y);
}
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.stroke();
// Animate the dot
const time = (Date.now() % 3000) / 3000;
const point = bezierFunction(time);
const x = point.x * width;
const y = height - point.y * height;
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
}
const animationFrame = requestAnimationFrame(function animate() {
drawCurve();
requestAnimationFrame(animate);
});
return () => cancelAnimationFrame(animationFrame);
}, [easing]);
return <canvas ref={canvasRef} width={200} height={200} className="border border-gray-300 rounded" />;
}
function cubicBezier(x1, y1, x2, y2) {
return function(t) {
const cx = 3 * x1;
const bx = 3 * (x2 - x1) - cx;
const ax = 1 - cx - bx;
const cy = 3 * y1;
const by = 3 * (y2 - y1) - cy;
const ay = 1 - cy - by;
const tSquared = t * t;
const tCubed = tSquared * t;
return {
x: t,
y: ay * tCubed + by * tSquared + cy * t
};
};
}
function EasingGuide() {
return (
<div className="bg-gray-100 p-6 rounded-lg mb-8">
<h2 className="text-2xl font-bold mb-4">🚀 Welcome to the Easing Battleground! 🎢</h2>
<p className="mb-4">Here's how to join the fun:</p>
<ol className="list-decimal list-inside mb-6">
<li className="mb-2"><strong>Create an Easing:</strong> You can use the <a href="https://ejfox-cavemanbezierapp.web.val.run">caveman easing generator</a> or the easing-creation tool of your choice.</li>
<li className="mb-2"><strong>Name Your Creation:</strong> Give your easing a catchy name. Be creative!</li>
<li className="mb-2"><strong>Sign Your Work:</strong> Optionally, add your name as the author.</li>
<li className="mb-2"><strong>Submit and Watch:</strong> Hit submit and see your easing come to life on the leaderboard!</li>
<li className="mb-2"><strong>Vote:</strong> Check out other easings and vote for your favorites. Use 👍 to upvote and 👎 to downvote.</li>
</ol>
<h3 className="text-xl font-semibold mb-2">💡 Tips for Great Easings:</h3>
<ul className="list-disc list-inside mb-6">
<li className="mb-2">Experiment with different curves to create unique motion effects.</li>
<li className="mb-2">Try to create easings that feel natural or surprisingly delightful.</li>
<li className="mb-2">Remember, all values should be between 0 and 1.</li>
</ul>
<h3 className="text-xl font-semibold mb-2">🧙‍♂️ Cubic-Bezier Magic:</h3>
<p className="mb-4">
Input your easing as a cubic-bezier function, like this:
<code className="bg-gray-200 px-2 py-1 rounded">cubic-bezier(0.05, 0.00, 0.16, 0.13)</code>
</p>
<h3 className="text-xl font-semibold mb-2">🏆 Leaderboard:</h3>
<p className="mb-4">
The leaderboard shows all submitted easings, sorted by score.
Watch the animated preview to see how each easing behaves!
ejfox-easingbattleground.web.val.run
September 3, 2024