-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
270 lines (226 loc) · 7.57 KB
/
index.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Springify</title>
</head>
<body>
<div class="container">
<div class="section section--title">
<h1 class="h1">Springify.js 🌿</h1>
<h2 class="subtitle">
Springify is a tiny lil' (under 1kb gzip) utility function for creating dynamic spring animations.
</h2>
<p>It's a bare bones but flexible utility that can be used to create a range of useful and fun interactions.</p>
</div>
<h2>Install via npm</h2>
<div class="section--code">
<pre>
<code class="language-bash">
npm i springify
</code>
</pre>
</div>
<h2>Basic usage</h2>
<div class="section--code">
<pre>
<code class="language-javascript">
import { Springify } from 'springify';
const spring = new Springify();
// Subscribe to updates. This will fire every frame and pass through the current values.
spring.subscribe(({ output, velocity }) => {
// output is the output value from the spring
// velocity is the velocity our spring is moving at
console.log(output);
console.log(velocity);
});
// Subscribe to the end event when the spring settles. This will fire once each time the spring stops.
spring.subscribe(({ output }) => {
// output is the output value from the spring once it has settled
console.log(output);
}, 'end');
// Update the value and springify will beging animating from the initial input value to the new one.
spring.input = 500;
</code>
</pre>
</div>
<h2>Default values</h2>
<div class="section--code">
<pre>
<code class="language-javascript">
const spring = new Springify({
input: 0, // the initial value
stiffness: 0, // effective range from 0 - 100;
damping: 30, // effective range from 0 - 100;
mass: 20, // effective range from 0 - 100;
});
</code>
</pre>
</div>
</div>
<div class="container">
<h1>Examples</h1>
<h2>Spring from --> to</h2>
<h4>Using static values</h4>
<p>Try interrupting the animation mid way through.</p>
<div class="section section--example-from-to">
<div class="sailboat">⛵</div>
</div>
<button class="btn sailboat--away">Sail away</button>
<button class="btn sailboat--back">Come back</button>
<div class="section--code">
<pre>
<code class="language-javascript">
import { Springify } from 'springify';
const sailboat = document.querySelector('.sailboat');
const sailAwayButton = document.querySelector('.sailboat--away');
const sailBackButton = document.querySelector('.sailboat--back');
let direction = 'right';
const springySailboat = new Springify({
stiffness: 10,
damping: 80,
mass: 50,
});
springySailboat.subscribe(({ output, velocity }) => {
sailboat.style.transform = `rotate(${velocity * -0.3}deg) scaleX(${direction === 'right' ? -1 : 1})`;
sailboat.style.left = `${output}%`;
});
sailAway.addEventListener('click', () => {
springySailboat.input = 100;
direction = 'right';
});
sailBack.addEventListener('click', () => {
springySailboat.input = 0;
direction = 'left';
});
</code>
</pre>
</div>
</div>
<div class="container">
<h2>Button press</h2>
<div class="section section--example-button">
<button class="demo-button">Press me</button>
<button class="demo-button">Press me</button>
<button class="demo-button">Press me</button>
</div>
<div class="section--code">
<pre>
<code class="language-javascript">
import { Springify } from 'springify';
const buttons = document.querySelectorAll('.demo-button');
buttons.forEach((button) => {
const springyButton = new Springify({
input: 1,
stiffness: 20,
damping: 30,
mass: 10,
});
springyButton.subscribe(({ output, velocity }) => {
button.style.transform = `scaleX(${output + velocity * 0.1}) scaleY(${output})`;
});
button.addEventListener('mousedown', () => {
springyButton.input = 0.75;
});
button.addEventListener('touchstart', (e) => {
e.preventDefault();
springyButton.input = 0.75;
});
button.addEventListener('mouseup', () => {
springyButton.input = 1.1;
});
button.addEventListener('mouseenter', () => {
springyButton.input = 1.1;
});
button.addEventListener('mouseout', () => {
springyButton.input = 1;
});
button.addEventListener('touchend', () => {
springyButton.input = 1;
});
});
</code>
</pre>
</div>
</div>
<div class="container">
<h2>Dynamic spring linked to scrolling</h2>
<div class="section section--example-spider">
<div class="spider">
<div class="spider__body">🕷</div>
<div class="spider__thread"></div>
</div>
</div>
<div class="section--code">
<pre>
<code class="language-javascript">
import { Springify } from 'springify';
const spider = document.querySelector('.spider');
const spiderArea = document.querySelector('.section--example-spider');
const springySpider = new Springify({
stiffness: 30,
damping: 50,
mass: 10,
});
springySpider.subscribe(({ output, velocity }) => {
spider.style.transform = `translateY(${output}px)`;
spiderBody.style.transform = `rotate(${1 + Math.abs(velocity * 1)})`;
});
window.addEventListener('scroll', () => {
springySpider.input = window.scrollY - spiderArea.offsetTop + window.innerHeight * 0.5;
});
</code>
</pre>
</div>
</div>
<div class="container">
<h2>Dynamic spring linked to mouse movements</h2>
<div class="section section--example-helicopter">
<div class="helicopter">🚁</div>
</div>
<div class="section--code">
<pre>
<code class="language-javascript">
import { Springify } from 'springify';
const helicopter = document.querySelector('.helicopter');
const helicopterDemo = document.querySelector('.section--example-helicopter');
const springyHelicopter = {
x: new Springify(),
y: new Springify(),
};
const helicopterTransform = (x: number, y: number, rotation: number) => {
return `translate(${x}px, ${y}px) rotate(${rotation}deg)`;
};
springyHelicopter.x.subscribe(({ output, velocity }) => {
helicopter.style.transform = helicopterTransform(output, springyHelicopter.y.output, velocity * 0.05);
});
const helicopterMove = (clientX, clientY) => {
// normalize the mouse coordinates to the helicopter demo area
const helicopterDemoRect = helicopterDemo.getBoundingClientRect();
const relativeX = clientX - (helicopterDemoRect.left + helicopterDemoRect.width * 0.5);
const relativeY = clientY - (helicopterDemoRect.top + helicopterDemoRect.height * 0.5);
// Send our relative mouse values as the inputs to the springs
springyHelicopter.x.input = relativeX;
springyHelicopter.y.input = relativeY;
};
helicopterDemo.addEventListener('mousemove', (e) => {
if (!e.clientX || !e.clientY) return;
helicopterMove(e.clientX, e.clientY);
});
helicopterDemo.addEventListener('mouseout', () => {
springyHelicopter.x.input = 0;
springyHelicopter.y.input = 0;
});
helicopterDemo.addEventListener('touchmove', (e) => {
if (e.touches === undefined) return;
helicopterMove(e.touches[0].clientX, e.touches[0].clientY);
});
</code>
</pre>
</div>
</div>
<script type="module" src="/src/demos/index.ts"></script>
</body>
</html>