Skip to content

Commit cfe9671

Browse files
authored
Spring physics (#169)
* init poc * api update, added more demos * more demos * minor demo udpates * folder cleanup * nit * adds keyboard support to all demos * expose for emulators * fix mobile layouts * stable number shifting * nit * adds build and readme entries
1 parent 505e06c commit cfe9671

33 files changed

+3236
-1
lines changed

.github/workflows/main.yml

+3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ jobs:
8585

8686
- name: Build Card Stack
8787
run: cd card-stack && npm install && npm run build
88+
89+
- name: Build Spring Physics
90+
run: cd spring-physics && npm install && npm run build
8891

8992
- name: Deploy to Firebase
9093
uses: w9jds/firebase-action@master

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ and expand the diversity of our skills.**
8989
[`Article`](https://web.dev/building-a-fab-component/)
9090
21. Carousels
9191
[`Demo`](https://gui-challenges.web.app/carousel/dist/)
92-
[`YouTube`](https://www.youtube.com/watch?v=CXJv6zM003M)
92+
[`YouTube`](https://www.youtube.com/watch?v=CXJv6zM003M)
93+
[`Article`](#)(coming soon)
9394
22. Crooked Grid Illusion
9495
[`Demo`](https://gui-challenges.web.app/crooked-illusion/dist/)
9596
[`YouTube`](https://www.youtube.com/watch?v=71jpjr7syc4)
@@ -106,3 +107,7 @@ and expand the diversity of our skills.**
106107
[`Demo`](https://gui-challenges.web.app/card-stack/dist/)
107108
[`YouTube`](https://www.youtube.com/watch?v=m4DKhRJeYx4)
108109
[`Article`](#)(coming soon)
110+
26. Spring Physics
111+
[`Demo`](https://gui-challenges.web.app/spring-physics/dist/)
112+
[`YouTube`](#)(coming soon)
113+
[`Article`](#)(coming soon)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.radius {
2+
block-size: 25vmin;
3+
aspect-ratio: 1;
4+
border-radius: var(--radius, 25%);
5+
background: blue;
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [radius] = $('.radius')
5+
6+
radius.physics = new SpringPhysics({
7+
startAt: 25,
8+
options: {
9+
namespace: '--radius',
10+
friction: 1,
11+
},
12+
update: ({namespace, value}) => {
13+
radius.style.setProperty(namespace, value+'%')
14+
}
15+
})
16+
17+
radius.on('pointerup keyup', e =>
18+
radius.physics.to(25))
19+
20+
radius.on('pointerdown keydown', e =>
21+
radius.physics.to(45))

spring-physics/demos/dots/dots.css

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.dots {
2+
display: grid;
3+
grid: 5vmin / auto-flow 5vmin;
4+
gap: 2.5vmin;
5+
}
6+
7+
.dots > * {
8+
aspect-ratio: 1;
9+
background: indigo;
10+
border-radius: 50%;
11+
translate: 0 var(--y);
12+
}

spring-physics/demos/dots/dots.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const dots = $('.dots > *')
5+
6+
dots.forEach(dot => {
7+
dot.physics = new SpringPhysics({
8+
startAt: 0,
9+
options: {
10+
namespace: '--y',
11+
friction: 1,
12+
},
13+
update: ({namespace, value}) => {
14+
dot.style.setProperty(namespace, value.toFixed()+'px')
15+
}
16+
})
17+
18+
dot.on('mouseover focus', e =>
19+
dot.physics.to(50))
20+
21+
dot.on('mouseout blur', e =>
22+
dot.physics.to(0))
23+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.emoji {
2+
font-size: 10vmin;
3+
will-change: transform;
4+
scale: var(--scale);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [emoji] = $('.emoji')
5+
6+
emoji.physics = new SpringPhysics({
7+
startAt: 1,
8+
options: {
9+
namespace: '--scale',
10+
},
11+
update: ({namespace, value}) => {
12+
emoji.style.setProperty(namespace, value)
13+
},
14+
})
15+
16+
emoji.on('pointerup keyup', e =>
17+
emoji.physics.to(1))
18+
19+
emoji.on('pointerdown keydown', e =>
20+
emoji.physics.to(.75))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.font-size {
2+
display: flex;
3+
}
4+
5+
.font-size > span {
6+
font-size: var(--fontsize, 48px);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const chars = $('.font-size > span')
5+
6+
chars.forEach(char => {
7+
char.physics = new SpringPhysics({
8+
startAt: 48,
9+
options: {
10+
namespace: '--fontsize',
11+
friction: 5,
12+
},
13+
update: ({namespace, value}) => {
14+
char.style.setProperty(namespace, value.toFixed() + 'px')
15+
}
16+
})
17+
18+
char.on('mouseover focus', e => {
19+
char.physics.to(100)
20+
char?.nextElementSibling?.physics.to(70)
21+
char?.previousElementSibling?.physics.to(70)
22+
})
23+
24+
char.on('mouseout blur', e => {
25+
char.physics.to(48)
26+
char?.nextElementSibling?.physics.to(48)
27+
char?.previousElementSibling?.physics.to(48)
28+
})
29+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.gradient {
2+
block-size: 25vmin;
3+
aspect-ratio: 16/9;
4+
background: linear-gradient(
5+
to right,
6+
hsl(var(--hue, 200) 75% 50%),
7+
hsl(calc(var(--hue, 200) + 25) 75% 54%)
8+
);
9+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [gradient] = $('.gradient')
5+
6+
gradient.physics = new SpringPhysics({
7+
startAt: 200,
8+
options: {
9+
namespace: '--hue',
10+
friction: 5,
11+
},
12+
update: ({namespace, value}) => {
13+
gradient.style.setProperty(namespace, value)
14+
}
15+
})
16+
17+
gradient.on('pointerup keyup', e =>
18+
gradient.physics.to(200))
19+
20+
gradient.on('pointerdown keydown', e =>
21+
gradient.physics.to(250))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.how-it-works {
2+
font-size: 4rem;
3+
font-variant-numeric: tabular-nums;
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [title] = $('.how-it-works')
5+
6+
title.physics = new SpringPhysics({
7+
startAt: 10,
8+
update: ({value}) => {
9+
title.textContent = value.toFixed()
10+
}
11+
})
12+
13+
title.on('pointerup keyup', e =>
14+
title.physics.to(10))
15+
16+
title.on('pointerdown keydown', e =>
17+
title.physics.to(100))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.letter-spacing {
2+
font-size: 3rem;
3+
letter-spacing: var(--letterspacing, 18px);
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [title] = $('.letter-spacing')
5+
6+
title.physics = new SpringPhysics({
7+
startAt: 3,
8+
options: {
9+
namespace: '--fontSize',
10+
friction: .2,
11+
},
12+
update: ({namespace, value}) => {
13+
title.style.setProperty('--letterspacing', (value*6)+'px')
14+
}
15+
})
16+
17+
title.on('pointerup keyup', e =>
18+
title.physics.to(3))
19+
20+
title.on('pointerdown keydown', e =>
21+
title.physics.to(5))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.playground {
2+
margin-block: 25vh;
3+
}
4+
5+
@media (min-width: 720px) {
6+
.playground {
7+
font-size: 2rem;
8+
}
9+
}
10+
11+
fieldset {
12+
border: none;
13+
display: grid;
14+
max-inline-size: max-content;
15+
margin-inline: auto;
16+
margin-block-end: 20px;
17+
}
18+
19+
fieldset > div {
20+
display: flex;
21+
align-items: center;
22+
justify-content: space-between;
23+
gap: 1ch;
24+
}
25+
26+
fieldset > div > label {
27+
min-inline-size: 12ch;
28+
}
29+
30+
fieldset > div > span {
31+
min-inline-size: 4ch;
32+
}
33+
34+
.track {
35+
display: grid;
36+
inline-size: 80vh;
37+
max-inline-size: 90vw;
38+
padding: 20px;
39+
background: hsl(0 0% 50% / 15%);
40+
border-radius: 1e5px;
41+
}
42+
43+
.ball {
44+
aspect-ratio: 1;
45+
inline-size: 15vh;
46+
background: deeppink;
47+
border-radius: 50%;
48+
transform: translateX(var(--x));
49+
}
50+
51+
#mass { accent-color: hotpink }
52+
#friction { accent-color: cyan }
53+
#tension { accent-color: lime }
54+
#start_velocity { accent-color: violet }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [track] = $('.track')
5+
const [ball] = $('.ball')
6+
7+
const distance = track.clientWidth - ball.clientWidth - 40
8+
const state = {pos: 0}
9+
10+
const init = () => {
11+
ball.physics = new SpringPhysics({
12+
startAt: state.pos,
13+
options: {
14+
namespace: '--x',
15+
mass: mass.value,
16+
tension: tension.value,
17+
friction: friction.value,
18+
start_velocity: start_velocity.value,
19+
},
20+
update: ({namespace, value}) => {
21+
ball.style.setProperty(namespace, value.toFixed()+'px')
22+
}
23+
})
24+
}
25+
26+
init()
27+
28+
$('fieldset').on('change', () => {
29+
mass_value.textContent = mass.value
30+
tension_value.textContent = tension.value
31+
friction_value.textContent = friction.value
32+
start_velocity_value.textContent = start_velocity.value
33+
init()
34+
})
35+
36+
track.on('click keydown', e => {
37+
state.pos = distance === state.pos
38+
? 0
39+
: distance
40+
41+
ball.physics.to(state.pos)
42+
})
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.rotate {
2+
inline-size: 25vmin;
3+
aspect-ratio: 1;
4+
background: hotpink;
5+
rotate: var(--rotate);
6+
}

spring-physics/demos/rotate/rotate.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {SpringPhysics} from '/spring-physics.js'
2+
import $ from 'blingblingjs'
3+
4+
const [rotate] = $('.rotate')
5+
6+
rotate.physics = new SpringPhysics({
7+
startAt: 0,
8+
options: {
9+
namespace: '--rotate',
10+
friction: 10,
11+
},
12+
update: ({namespace, value}) => {
13+
rotate.style.setProperty(namespace, value+'turn')
14+
}
15+
})
16+
17+
rotate.on('pointerdown keydown', e => rotate.physics.to(.5))
18+
rotate.on('pointerup keyup', e => rotate.physics.to(0))

0 commit comments

Comments
 (0)