How do I pause the animation in React Spring?

Asked
Active3 hr before
Viewed126 times

9 Answers

pauseanimationspringreact
90%

In the current version of react-spring v9.2 you can use useSpring and pass it a function that return the styles and api to control the animation state, using this api we can easily pause and resume an animation,Connect and share knowledge within a single location that is structured and easy to search.,in case you want to pause after 3 seconds you can use useEffect with setTimeout,I'm trying to pause the animation in React Spring after 3 seconds, I tried the following code but it didn't work.

In the current version of react-spring v9.2 you can use useSpring and pass it a function that return the styles and api to control the animation state, using this api we can easily pause and resume an animation

function TestComponent() {

  const [pause, setPause] = useState(false);

  const [styles, api] = useSpring(() => ({
    from: { opacity: 0 },
    to: { opacity: 1 },
    config: {
      mass: 18.6,
      tension: 7,
      friction: 161
    },
  }))

  return (
    <>
      <animated.div style={styles}>
        {'Fade in effect'}
      </animated.div>

      <button onClick={() => { api.pause() }}>{'pause'}</button>
      <button onClick={() => { api.resume() }}>{'resume'}</button>
    </>
  );

}
load more v
88%

I've tried to put an infinite friction, but bringing friction back to default would not resume the animation.,Is there a simple way to pause the animation of a Spring?,Do you have the option to use hooks? This would make it easier. A Spring is a declaration of intent, to pause would essentially conflict with the props-declaration. You can do it, but only through reaching into internals <Spring ref={r => r && r.controller.cancel()} ... />,I'd like to pause an ongoing animation, and be able to resume.

The pause and cancel props are available in v9. #985

pause
load more v
72%

Resumes some of the paused spring animations.,Freezes some of the spring animations in time.,Resumes the active animation.,bring your components to life with simple spring animation primitives

The Controller is react-spring's heart. All primitives use it internally (including hooks). If you dislike render-props, and maybe hooks are too radical for you, then perhaps this is what you are looking for as it gives you full manual control without having to worry about loose-end animation handles. The api is very similar to the useSpring hook.

import { Controller, animated } from 'react-spring'
class Test extends React.Component {  state = { show: true }  animations = new Controller({ opacity: 0 })
  toggle = () => this.setState(state => ({ show: !state.show }))
  render() {    const props = this.animations.update({ opacity: this.state.show ? 1 : 0 })    return (      <>        <button onClick={this.toggle}>click</button>        <animated.div style={props}>I will fade</animated.div>      </>    )  }}
import { Controller, animated } from 'react-spring'
class Test extends React.Component {  state = { show: true }  animations = new Controller({ opacity: 0 })
  toggle = () => this.setState(state => ({ show: !state.show }))
  render() {    const props = this.animations.update({ opacity: this.state.show ? 1 : 0 })    return (      <>        <button onClick={this.toggle}>click</button>        <animated.div style={props}>I will fade</animated.div>      </>    )  }}

Call a function once per spring value.

controller.each((spring, key) => key === 'opacity' ? spring.set(1) : spring.set(0))
controller.each((spring, key) => key === 'opacity' ? spring.set(1) : spring.set(0))

Get the current values of our springs.

const springValues = controller.get()
const springValues = controller.get()

Freeze the active animation in time.

contoller.pause()
contoller.pause()

Freezes some of the spring animations in time.

contoller.pause(['opacity', 'color'])
contoller.pause(['opacity', 'color'])

Resumes the active animation.

contoller.resume()
contoller.resume()

Resumes some of the paused spring animations.

contoller.resume(['opacity', 'color'])
contoller.resume(['opacity', 'color'])

Set the current values without animating.

contoller.set({
   opacity: 1,
   color: 0x0000ff
})
contoller.set({
   opacity: 1,
   color: 0x0000ff
})

Start the queued animations for every spring, and resolve the returned promise once all queued animations have finished or been cancelled.

controller.start()
controller.start()

When you pass a queue (instead of nothing), that queue is used instead of the queued animations added with the update method, which are left alone.

controller.start({
   opacity: 1,
   color: 0x0000ff
})
controller.start({
   opacity: 1,
   color: 0x0000ff
})

Stop all animations.

contoller.stop()
contoller.stop()

Stop animations for the given keys.

contoller.stop(['opacity', 'color'])
contoller.stop(['opacity', 'color'])

Cancel animations for the given keys.

contoller.stop(true, ['opacity', 'color'])
contoller.stop(true, ['opacity', 'color'])

Push an update onto the queue of each value.

contoller.update({
   opacity: 1,
   color: 0x0000ff
})
contoller.update({
   opacity: 1,
   color: 0x0000ff
})
load more v
65%

In this case, there is no re-rendering. This method is mostly applied for fast occurring updates. It also has an optional argument (stop) to stop animation.,The above snippet uses the listed props to set the initial and final conditions of the elements using the ternary operators to indicate the switch.,As we mentioned earlier, Spring/useSpring makes use of two props from and to to show the initial position and the end position of the animation like so:,In response to last message

The best way to add React Spring to your application will be via the package managers. Simply open a terminal window on your project’s root directory and run the installation command below:

npm install react - spring
#OR
yarn add react - spring
load more v
75%

Spectrum is now read-only. Learn more about the decision in our official announcement.,A community dedicated to react-spring

[spring, set, stop] = useSpring(() => ({someSpringProps})) ;stop()////in the render:<a.cirvle style={{...spring}}/>
40%

The pause prop literally freezes animations in time.,When used in a declarative update, the declared animation is paused until the pause prop equals false again. Then the animation will continue from its current value.,When a dependency array is passed, the useSpring and useSprings hooks each return an animate function.,Once the cancel prop turns from true to false, the declared animation will resume or reset, depending on the given props.

yarn add react - spring @npm: @react - spring / web @9 .0 .0 - rc .1
yarn add react - spring @npm: @react - spring / web @9 .0 .0 - rc .1

Click here for the latest version.

https: //cdn.jsdelivr.net/npm/@react-spring/web@next/index.umd.min.js
https: //cdn.jsdelivr.net/npm/@react-spring/web@next/index.umd.min.js

In the past two major versions, the "Render Props API" and "Hooks API" were provided by separate modules. In fact, each API had its own implementation of the internal Controller class, which was bad for maintenance.

// v8import { useSpring } from 'react-spring'import { Spring } from 'react-spring/renderprops'
// v8import { useSpring } from 'react-spring'import { Spring } from 'react-spring/renderprops'

The new version unifies these APIs into a single module!

// v9import { Spring, useSpring } from 'react-spring'
// v9import { Spring, useSpring } from 'react-spring'

When a dependency array is passed, the useSpring and useSprings hooks each return an animate function.

const [style, animate] = useSpring({
   x: 0,
   y: 0
}, []) useEffect(() => {
   animate({
      x: 100,
      y: 100
   })
}, [])
const [style, animate] = useSpring({
   x: 0,
   y: 0
}, []) useEffect(() => {
   animate({
      x: 100,
      y: 100
   })
}, [])
  • x, y, z
  • translate, translateX, translateY, translate3d
  • rotate, rotateX, rotateY, rotate3d
  • scale, scaleX, scaleY, scale3d
  • skew, skewX, skewY
  • matrix, matrix3d
const { x, y } = useSpring({ x: 0, y: 0 })// v8import { to } from 'react-spring'const transform = to([x, y], (x, y) => `translate(${x}px, ${y}px)`)return <a.div style={{ transform }} />// v9return <a.div style={{ x, y }} />
const { x, y } = useSpring({ x: 0, y: 0 })// v8import { to } from 'react-spring'const transform = to([x, y], (x, y) => `translate(${x}px, ${y}px)`)return <a.div style={{ transform }} />// v9return <a.div style={{ x, y }} />

Use loop: true to repeat an animation.

Pass a function to be called after each loop. Return true to continue looping, or false to stop.

Define a loop object to customize the loop animation separately from the initial animation. It may contain any of the useSpring props. For example, if reverse: true is used, the loop animation will reverse on each loop.

The loop object is always merged into a copy of the props object it was defined in. The following example shows a loop animation that inherits its config prop.

The FrameValue class (inherited by SpringValue and Interpolation) allows for animations toward or from an observable FluidValue object. You can make any library work like this with react-spring by following this guide.

The following example never animates, because cancel is always true.

useSpring({
   cancel: true,
   from: {
      x: 0
   },
   to: {
      x: 100
   },
})
useSpring({
   cancel: true,
   from: {
      x: 0
   },
   to: {
      x: 100
   },
})

The cancel prop even prevents delayed updates. 😎

const [style, animate] = useSpring(() => ({
   x: 0
})) // Pass this to an element.const onClick = () => {  animate({ x: 100, delay: 500 })  // Prevent the previous update. 🤣  animate({ cancel: true })}
const [style, animate] = useSpring(() => ({
   x: 0
})) // Pass this to an element.const onClick = () => {  animate({ x: 100, delay: 500 })  // Prevent the previous update. 🤣  animate({ cancel: true })}

To cancel the animation of specific keys, you can pass a single key, an array of keys, or a (key: string) => boolean function.

// Using a single keycancel: 'x',// Using an array of keyscancel: ['x', 'y'],// Using a functioncancel: key => key !== 'x',
// Using a single keycancel: 'x',// Using an array of keyscancel: ['x', 'y'],// Using a functioncancel: key => key !== 'x',

The following example will pause the animation while your mouse is over it. (Note: The useHover hook is theoretical)

const isHovering = useHover() useSpring({
   pause: isHovering,
   from: {
      x: 0
   },
   to: {
      x: 100
   },
   loop: true,
})
const isHovering = useHover() useSpring({
   pause: isHovering,
   from: {
      x: 0
   },
   to: {
      x: 100
   },
   loop: true,
})

The config prop can now be partially updated.

const {
   x
} = useSpring({
   from: {
      x: 0
   },
   config: {
      frequency: 1
   },
}) useEffect(() => {
   x.start({
      config: {
         velocity: 0
      }
   }) x.start({
      config: {
         friction: 20
      }
   })
}, [])
const {
   x
} = useSpring({
   from: {
      x: 0
   },
   config: {
      frequency: 1
   },
}) useEffect(() => {
   x.start({
      config: {
         velocity: 0
      }
   }) x.start({
      config: {
         friction: 20
      }
   })
}, [])

For the declarative API, this prop is true by default. In the following example, the onRest handler is inherited by every update passed to animate, except when a call has its own onRest prop defined.

useSpring({
   to: async animate => {
      ...
   },
   onRest: () => {
      ...
   }
})
useSpring({
   to: async animate => {
      ...
   },
   onRest: () => {
      ...
   }
})

Imperative updates can use default: true to set default props. When an async to prop is defined by an imperative update, it will inherit props from the imperative update like this:

useSpring({
         from: {
            x: 0
         },
         to: async animate => { // The `config` prop below is inherited by    // both objects in the `to` array.    await animate({      to: [{ x: 100 }, { x: 0 }],      config: { tension: 100 },    })  },})
useSpring({
         from: {
            x: 0
         },
         to: async animate => { // The `config` prop below is inherited by    // both objects in the `to` array.    await animate({      to: [{ x: 100 }, { x: 0 }],      config: { tension: 100 },    })  },})

For example, both the ref prop and the animate function will inherit the default props defined below (in the useSpring props function).

const ref = useRef() const [{
      x
   }, animate] = useSpring(() => ({
      x: 0,
      onRest: () => {
         ...
      },
      ref,
   })) useEffect(async () => { // Animate to 100 with the ref API.  await ref.current.start({ x: 100 })  // Animate to 0 with the function API.  await animate({ x: 0 })}, [])
const ref = useRef() const [{
      x
   }, animate] = useSpring(() => ({
      x: 0,
      onRest: () => {
         ...
      },
      ref,
   })) useEffect(async () => { // Animate to 100 with the ref API.  await ref.current.start({ x: 100 })  // Animate to 0 with the function API.  await animate({ x: 0 })}, [])

In this example, we are setting true as the default value of immediate. This affects all future animations owned by the useSpring call, whether or not they are declarative or imperative.

const {
   x
} = useSpring({
      x: 0,
      default: {
         immediate: true
      },
   }) useEffect(() => { // This will be immediate.  x.start(100)})
const {
   x
} = useSpring({
      x: 0,
      default: {
         immediate: true
      },
   }) useEffect(() => { // This will be immediate.  x.start(100)})

Props like onRest can now be defined on a per-key basis.

useSpring({
   from: {
      x: 0,
      y: 0
   },
   onRest: {
      x: () => console.log('x.onRest'),
      y: () => console.log('y.onRest'),
   },
})
useSpring({
   from: {
      x: 0,
      y: 0
   },
   onRest: {
      x: () => console.log('x.onRest'),
      y: () => console.log('y.onRest'),
   },
})

The onDelayEnd prop is called for every non-cancelled update, after its delay is finished, but before the props are merged. It receives a props object and the affected SpringValue object.

useSpring({
   onDelayEnd(props, spring) {
      console.log('onDelayEnd:', props, spring)
   },
})
useSpring({
   onDelayEnd(props, spring) {
      console.log('onDelayEnd:', props, spring)
   },
})

The onProps prop is called immediately after all props have been merged into the animation of the affected SpringValue object, but before the first frame of an animation initiated by the props.

useSpring({
         onProps(props, spring) {
            console.log('onProps:', { // Inspect the update props.      props,      // Inspect the animated value.      spring,      // Inspect the animation state.      ...spring.animation,    })  },})
useSpring({
         onProps(props, spring) {
            console.log('onProps:', { // Inspect the update props.      props,      // Inspect the animated value.      spring,      // Inspect the animation state.      ...spring.animation,    })  },})

Modify animations within the given children, but only the animations created by the hook API (eg: useSpring) or renderprops API (eg: <Spring>) are affected. Animations created with new SpringValue() or new Controller() are unaffected.

<SpringContext cancel={true}>  <App /></SpringContext>
<SpringContext cancel={true}>  <App /></SpringContext>

In the example below, only Page2 can play its animations. Pretend this element tree is rendered more dynamically, and this code is a static representation.

<SpringContext pause={true}>  <Page1 />  <SpringContext pause={false}>    <Page2 />  </SpringContext>  <Page3 /></SpringContext>
<SpringContext pause={true}>  <Page1 />  <SpringContext pause={false}>    <Page2 />  </SpringContext>  <Page3 /></SpringContext>

When true, all animations are finished immediately. The requestAnimationFrame loop is skipped entirely. Any onRest callbacks are still invoked.

import {
   Globals
} from 'react-spring'
Globals.assign({
   skipAnimation: true
})
import {
   Globals
} from 'react-spring'
Globals.assign({
   skipAnimation: true
})

Combine skipAnimation with prefers-reduced-motion to gracefully disable or reduce the motion of your animations. The react-reduce-motion package can help with that.

import {
   Globals
} from 'react-spring'
import {
   useReduceMotion
} from 'react-reduce-motion'
const prefersReducedMotion = useReduceMotion() useEffect(() => {
   Globals.assign({
      skipAnimation: prefersReducedMotion,
   })
}, [prefersReducedMotion])
import {
   Globals
} from 'react-spring'
import {
   useReduceMotion
} from 'react-reduce-motion'
const prefersReducedMotion = useReduceMotion() useEffect(() => {
   Globals.assign({
      skipAnimation: prefersReducedMotion,
   })
}, [prefersReducedMotion])

numbers

new SpringValue(0)
new SpringValue(0)

strings with numbers

new SpringValue('0px 10px') new SpringValue('rgba(0, 0, 255, 1)')
new SpringValue('0px 10px') new SpringValue('rgba(0, 0, 255, 1)')

named colors

new SpringValue('red')
new SpringValue('red')

and arrays of the preceding types

new SpringValue([0, '1em'])
new SpringValue([0, '1em'])

Get the current value.

const value = spring.get()
const value = spring.get()

Set the current value, replace the goal value, and stop animating.

spring.set(1)
spring.set(1)

Add an update to the queue array. All updates in the queue are applied at the same time.

const delays = [0, 100, 300]
for (const delay of delays) {
   spring.update({
      x: delay
   })
}
spring.start()
const delays = [0, 100, 300]
for (const delay of delays) {
   spring.update({
      x: delay
   })
}
spring.start()

The returned Promise resolves after every animation triggered by the queue array has either finished or been cancelled.

await spring.start()
await spring.start()

The returned promise is resolved after the animation is finished or cancelled. If a start call triggers no animation, the promise resolves immediately.

await spring.start({
   from: 0,
   to: 1
})
await spring.start({
   from: 0,
   to: 1
})
  • finished property is only true when every animation triggered by the queue was finished before being stopped or cancelled.

  • cancelled property is only false when all updates in the queue were never cancelled.

await spring.start([{
   from: 0
}, {
   to: 10
}, {
   to: 20,
   delay: 1000
}, ])
await spring.start([{
   from: 0
}, {
   to: 10
}, {
   to: 20,
   delay: 1000
}, ])

The onStart prop is called whenever finish is called before the first frame. The onRest prop is called with finished: true as expected.

spring.finish()
spring.finish()

Jump to the given value immediately, and call the onStart and onRest props the same way .finish() does.

spring.finish(100)
spring.finish(100)

The goal value is replaced with the current value.

spring.stop()
spring.stop()

Restart the animation using its cached from and to values.

spring.reset()
spring.reset()

You will probably never call this.

// Advance a single frame.spring.advance(1000 / 60)
// Advance a single frame.spring.advance(1000 / 60)

Check for the given phase.

if (spring.is('PAUSED')) {
   return
}
if (spring.is('PAUSED')) {
   return
}

When defined, the to prop can be an object with this key defined as a property.

spring.key = 'foo'
spring.start({
   to: {
      foo: '180deg'
   }
})
spring.key = 'foo'
spring.start({
   to: {
      foo: '180deg'
   }
})
load more v
22%

The animation is janky on firefox android(at least on my device) but smooth on chrome android. I found out (with react profiler) that render <RacingBarGroup> (which call useTransition for animating the bars) cost lots of time. Is there any idea for optimizing performance?,I noticed that the other bar chart race implementation using vanilla js and d3 is smooth on firefox android (for example https://observablehq.com/@d3/bar-chart-race), so I'm not sure this issue is due to my code, react-spring or react.,I'm building bar chart race animation with useTransition. here is the source and demo. I have the following questions:,The animation is janky on firefox android(at least on my device) but smooth on chrome android. I found out (with react profiler) that render <RacingBarGroup> (which call useTransition for animating the bars) cost lots of time. Is there any idea for optimizing performance? I noticed that the other bar chart race implementation using vanilla js and d3 is smooth on firefox android (for example https://observablehq.com/@d3/bar-chart-race), so I'm not sure this issue is due to my code, react-spring or react.

load more v
60%

Let’s consider the canonical “Hello world” of animation: fading content in and out. Let’s stop for a moment and consider how we’d switch opacity on and off without any kind of animation. It’d look something like this:,First, we’ll add some state to our modal that switches animation on and off.,Animation is one of the trickier things to get right with React. In this post, I’ll try to provide the introduction to react-spring I wish I had when I first started out, then dive into some interesting use cases. While react-spring isn’t the only animation library for React, it’s one of the more popular (and better) ones.,…we’ll declare our transition function like this:

Let’s consider the canonical “Hello world” of animation: fading content in and out. Let’s stop for a moment and consider how we’d switch opacity on and off without any kind of animation. It’d look something like this:

export default function App() {
  const [showing, setShowing] = useState(false);
  return (
    <div>
      <div style={{ opacity: showing ? 1 : 0 }}>
        This content will fade in and fade out
      </div>
      <button onClick={() => setShowing(val => !val)}>Toggle</button>
      <hr />
    </div>
  );
}
load more v
48%

Animations add life to design and improve the UX of an app. ,useSpring – a single animation that changes the state of the animation a => b.,At the moment, the React Spring library contains 5 hooks:,We’ll start this React Spring animation tutorial with the simplest hook – useSpring. It transforms the passed values into animated ones.

For animation on appearance it will be enough to indicate the following:

import {
   animated,
   useSpring
} from "React Spring";
load more v

Other "pause-animation" queries related to "How do I pause the animation in React Spring?"