@@ -3,51 +3,59 @@ import { useSpring, animated } from 'react-spring'
33import { useDrag } from 'react-use-gesture'
44import './styles.css'
55
6+ const modes = {
7+ pong : 0 , // The min/max values deflect the decay animation
8+ bounce : 0 , // The animation bounces instead of overshooting. Try both directions
9+ skipFinish : 0 , // This demonstrates "from !== to" when truthy, else "from === to" (it should work either way)
10+ }
11+
612const [ min , max ] = [ - 250 , 250 ]
13+ const clamp = value => Math . max ( min , Math . min ( max , value ) )
714
815export default function Inertia ( ) {
9- const [ { y } , set ] = useSpring ( ( ) => ( { y : 0 } ) )
16+ const { y } = useSpring ( { y : 0 } )
1017
1118 const bind = useDrag (
12- ( { down, movement : [ , dy ] , vxvy : [ , vy ] , memo = y . getValue ( ) } ) => {
13- if ( down ) set ( { y : dy + memo , onFrame : ( ) => { } , immediate : true } )
19+ ( { down, movement : [ , dy ] , vxvy : [ , vy ] , memo = y . get ( ) } ) => {
20+ if ( down ) y . set ( clamp ( dy + memo ) )
1421 else inertia ( dy + memo + 1 , vy )
1522 return memo
1623 }
1724 )
1825
19- const springBounce = React . useCallback (
20- velocity => {
21- set ( {
22- y : velocity > 0 ? max : min ,
23- onFrame : ( ) => { } , // <-- this is annoying :)
24- config : { velocity : velocity * 3 } ,
25- } )
26- } ,
27- [ set ]
28- )
26+ const springBounce = velocity =>
27+ y . animate ( {
28+ to : velocity > 0 ? max : min ,
29+ config : {
30+ velocity : velocity ,
31+ tension : 30 ,
32+ friction : 2 ,
33+ clamp : modes . bounce ? 0.7 : false ,
34+ precision : 0.005 ,
35+ } ,
36+ onRest : ( ) => console . log ( 'BOUNCE END' ) ,
37+ } )
2938
30- const inertia = React . useCallback (
31- ( position , velocity ) => {
32- set ( {
33- to : async ( next , stop ) => {
34- await next ( {
35- y : position ,
36- onFrame : async v => {
37- const vel = y . lastVelocity
39+ const inertia = ( position , velocity ) =>
40+ y . animate ( {
41+ y : position ,
42+ onChange : async val => {
43+ const vel = y . node . lastVelocity
44+ if ( ( val > max && vel > 0 ) || ( val < min && vel < 0 ) ) {
45+ if ( modes . pong ) {
46+ inertia ( y . get ( ) , - vel )
47+ } else {
48+ if ( ! modes . skipFinish ) {
49+ y . finish ( vel > 0 ? max : min )
50+ }
51+ springBounce ( vel )
52+ }
53+ }
54+ } ,
55+ config : { decay : true , velocity } ,
56+ onRest : ( ) => console . log ( 'INERTIA END' ) ,
57+ } )
3858
39- if ( ( v . y > max && vel > 0 ) || ( v . y < min && vel < 0 ) ) {
40- stop ( )
41- springBounce ( vel )
42- }
43- } ,
44- config : { decay : true , velocity } ,
45- } )
46- } ,
47- } )
48- } ,
49- [ y , set , springBounce ]
50- )
5159 // Now we're just mapping the animated values to our view, that's it. Btw, this component only renders once. :-)
5260 return (
5361 < div className = "inertia" >
0 commit comments