Skip to content

Commit 2ab4d27

Browse files
committed
useTransition(items, keys, config)
1 parent ab66716 commit 2ab4d27

File tree

16 files changed

+220
-38
lines changed

16 files changed

+220
-38
lines changed

examples/components/examples-hooks.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,9 @@ return items.map(i =>
217217
tags: ['useSprings'],
218218
},
219219
{
220-
name: 'freshtilledsoil',
221-
title: 'Freshtilledsoil stresstest',
222-
link: 'https://codesandbox.io/embed/j0y0vpz59',
223-
tags: ['useChain'],
220+
name: 'masonry-grid',
221+
title: 'Masonry grid',
222+
link: 'https://codesandbox.io/embed/26mjowzpr',
223+
tags: ['useTransition'],
224224
},
225225
]

examples/components/examples-tests.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,10 @@ export default [
55
link: '#',
66
tags: ['controller'],
77
},
8+
{
9+
name: 'freshtilledsoil',
10+
title: 'Freshtilledsoil stresstest',
11+
link: 'https://codesandbox.io/embed/j0y0vpz59',
12+
tags: ['useChain'],
13+
},
814
]

examples/demos/chain-animation/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ export default function App() {
2424

2525
// 2. create transition-refs
2626
const transRef = useRef()
27-
const transitions = useTransition({
28-
items: open ? data : [],
29-
keys: item => item.name,
27+
const transitions = useTransition(open ? data : [], item => item.name, {
3028
from: { opacity: 0, transform: 'scale(0)' },
3129
enter: { opacity: 1, transform: 'scale(1)' },
3230
leave: { opacity: 0, transform: 'scale(0)' },

examples/demos/image-fade/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ const slides = [
2828
export default function App() {
2929
const [index, set] = useState(0)
3030

31-
const transitions = useTransition({
32-
items: slides[index],
33-
keys: item => item.id,
31+
const transitions = useTransition(slides[index], item => item.id, {
3432
from: { opacity: 0 },
3533
enter: { opacity: 1 },
3634
leave: { opacity: 0 },

examples/demos/list-reordering/index.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@ export default function App() {
99
useEffect(() => void setInterval(() => set(shuffle), 3000), [])
1010

1111
let height = 0
12-
const transitions = useTransition({
13-
items: rows.map(data => ({
14-
...data,
15-
y: (height += data.height) - data.height,
16-
})),
17-
keys: d => d.name,
18-
from: { height: 0, opacity: 0 },
19-
leave: { height: 0, opacity: 0 },
20-
enter: ({ y, height }) => ({ y, height, opacity: 1 }),
21-
update: ({ y, height }) => ({ y, height }),
22-
config: { mass: 5, tension: 500, friction: 150 },
23-
})
12+
const transitions = useTransition(
13+
rows.map(data => ({ ...data, y: (height += data.height) - data.height })),
14+
d => d.name,
15+
{
16+
from: { height: 0, opacity: 0 },
17+
leave: { height: 0, opacity: 0 },
18+
enter: ({ y, height }) => ({ y, height, opacity: 1 }),
19+
update: ({ y, height }) => ({ y, height }),
20+
config: { mass: 5, tension: 500, friction: 150 },
21+
}
22+
)
2423

2524
return (
2625
<div className="list-reorder-scroll">
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
export default [
2+
{
3+
css:
4+
'url(https://images.pexels.com/photos/416430/pexels-photo-416430.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
5+
height: 150,
6+
},
7+
{
8+
css:
9+
'url(https://images.pexels.com/photos/1103970/pexels-photo-1103970.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
10+
height: 300,
11+
},
12+
{
13+
css:
14+
'url(https://images.pexels.com/photos/911738/pexels-photo-911738.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
15+
height: 300,
16+
},
17+
{
18+
css:
19+
'url(https://images.pexels.com/photos/358574/pexels-photo-358574.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
20+
height: 300,
21+
},
22+
{
23+
css:
24+
'url(https://images.pexels.com/photos/1738986/pexels-photo-1738986.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
25+
height: 300,
26+
},
27+
{
28+
css:
29+
'url(https://images.pexels.com/photos/96381/pexels-photo-96381.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
30+
height: 300,
31+
},
32+
{
33+
css:
34+
'url(https://images.pexels.com/photos/1005644/pexels-photo-1005644.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
35+
height: 200,
36+
},
37+
{
38+
css:
39+
'url(https://images.pexels.com/photos/227675/pexels-photo-227675.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
40+
height: 300,
41+
},
42+
{
43+
css:
44+
'url(https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
45+
height: 200,
46+
},
47+
{
48+
css:
49+
'url(https://images.pexels.com/photos/327482/pexels-photo-327482.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
50+
height: 400,
51+
},
52+
{
53+
css:
54+
'url(https://images.pexels.com/photos/988872/pexels-photo-988872.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
55+
height: 200,
56+
},
57+
{
58+
css:
59+
'url(https://images.pexels.com/photos/249074/pexels-photo-249074.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
60+
height: 150,
61+
},
62+
{
63+
css:
64+
'url(https://images.pexels.com/photos/310452/pexels-photo-310452.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
65+
height: 400,
66+
},
67+
{
68+
css:
69+
'url(https://images.pexels.com/photos/380337/pexels-photo-380337.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260)',
70+
height: 200,
71+
},
72+
]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { useRef, useState, useEffect } from 'react'
2+
import ResizeObserver from 'resize-observer-polyfill'
3+
4+
export function useMeasure() {
5+
const ref = useRef()
6+
const [bounds, set] = useState({ left: 0, top: 0, width: 0, height: 0 })
7+
const [ro] = useState(
8+
() => new ResizeObserver(([entry]) => set(entry.contentRect))
9+
)
10+
useEffect(() => (ro.observe(ref.current), ro.disconnect), [])
11+
return [{ ref }, bounds]
12+
}
13+
14+
export function useMedia(queries, values, defaultValue) {
15+
const match = () =>
16+
values[queries.findIndex(q => matchMedia(q).matches)] || defaultValue
17+
const [value, set] = useState(match)
18+
useEffect(() => {
19+
const handler = () => set(match)
20+
window.addEventListener('resize', handler)
21+
return () => window.removeEventListener(handler)
22+
}, [])
23+
return value
24+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, { useState, useEffect } from 'react'
2+
import { useTransition, animated as a, config } from 'react-spring/hooks'
3+
import shuffle from 'lodash/shuffle'
4+
import { useMeasure, useMedia } from './helpers'
5+
import data from './data'
6+
import './styles.css'
7+
8+
export default function App() {
9+
const columns = 6
10+
const [bind, { width }] = useMeasure()
11+
const [items, set] = useState(data)
12+
13+
let heights = new Array(columns).fill(0)
14+
const transItems = items.map((child, i) => {
15+
const column = heights.indexOf(Math.min(...heights))
16+
const xy = [
17+
(width / columns) * column,
18+
(heights[column] += child.height / 2) - child.height / 2,
19+
]
20+
return { ...child, xy, width: width / columns, height: child.height / 2 }
21+
})
22+
23+
const transitions = useTransition(width ? transItems : [], item => item.css, {
24+
from: ({ xy, width, height }) => ({ xy, width, height: 0, opacity: 0 }),
25+
enter: ({ xy, width, height }) => ({ xy, width, height, opacity: 1 }),
26+
update: ({ xy, width, height }) => ({ xy, width, height }),
27+
leave: { height: 0, opacity: 0 },
28+
config: config.stiff,
29+
trail: 25,
30+
})
31+
32+
useEffect(() => void setInterval(() => set(shuffle), 2000), [])
33+
34+
return (
35+
<div className="mgrid">
36+
<div
37+
{...bind}
38+
className="mgrid-list"
39+
style={{ height: Math.max(...heights) }}>
40+
{transitions.map(({ item, props: { xy, ...rest }, key }) => (
41+
<a.div
42+
key={key}
43+
style={{
44+
transform: xy.interpolate(
45+
(x, y) => `translate3d(${x}px,${y}px,0)`
46+
),
47+
...rest,
48+
}}>
49+
<div style={{ backgroundImage: item.css }} />
50+
</a.div>
51+
))}
52+
</div>
53+
</div>
54+
)
55+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.mgrid {
2+
overflow: auto;
3+
display: flex;
4+
justify-content: center;
5+
background: #f0f0f0;
6+
padding: 8px;
7+
}
8+
9+
.mgrid-list {
10+
position: relative;
11+
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto,
12+
segoe ui, arial, sans-serif;
13+
width: 100%;
14+
height: 100%;
15+
}
16+
17+
.mgrid-list > div {
18+
position: absolute;
19+
will-change: transform, width, height, opacity;
20+
padding: 8px;
21+
}
22+
23+
.mgrid-list > div > div {
24+
position: relative;
25+
background-size: cover;
26+
background-position: center center;
27+
width: 100%;
28+
height: 100%;
29+
overflow: hidden;
30+
text-transform: uppercase;
31+
font-size: 10px;
32+
line-height: 10px;
33+
border-radius: 4px;
34+
box-shadow: 0px 10px 50px -10px rgba(0, 0, 0, 0.2);
35+
}

examples/demos/multistage-transitions/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ export default function MultiStageTransition() {
66
const ref = useRef([])
77
const [items, set] = useState([])
88

9-
const transitions = useTransition({
10-
items,
9+
const transitions = useTransition(items, p => p, {
1110
from: {
1211
opacity: 0,
1312
height: 0,

0 commit comments

Comments
 (0)