Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
doc
 
 
src
 
 
 
 
 
 
 
 
 
 

README.md

CircleCI

animate

  1. About
  2. Installation
  3. Example
  4. API

About

animate() is an alternative to Element.animate(), the native interface provided by the Web Animation API (WAAPI) to animate CSS properties, which is not supported in all browsers yet (can I use it?), with some extra features.

animate() returns an object that should conform to the native Animation interface, except for the properties and methods listed below.

Each write on Element will be delayed and batched at the end of the runtime, to prevent style/layout recalculations.

Demo: https://codepen.io/creative-wave/pen/XWWRoWv

Supported WAAPI features

Feature Status Notes
Animation properties
currentTime
effect Will not be implemented.
finished
id
pending
playState
playbackRate
ready May be implemented later.
startTime
timeline Will not be implemented.
Animation methods
cancel
finish
oncancel Will not be implemented.
onfinish Will not be implemented.
pause
play
reverse
updatePlaybackRate Will not be implemented.
Keyframes
Format 1
Format 2
composite
- replace (default)
- add Will not be implemented.
- accumulate Will not be implemented.
easing
offset
Options
as Number (duration)
duration
easing
delay
direction
- normal (default)
- reverse
- alternate
- alternate-reverse
endDelay
fill
- auto (default)
- none
- backwards
- forwards
- both
id
iterations
iterationStart
pseudoElement Will not be implemented.

Extra features

  1. Custom timing (easing) function which would be hard to reproduce using keyframes (eg. multiple bounces)
  2. Custom functions to interpolate and set animated values, eg. to animate the definition attribute of an SVG <path> using unique delay/duration for each point (demo), or to animate a property specified as animatable in a draft specification but that couldn't be animated yet (demo with the y attribute of a <pattern>), or to animate a property which is not a CSS property, such as Element.innerText
  3. A then() interface to execute a callback at the end of an animation

Installation

  npm i @cdoublev/animate

This package doesn't include a polyfill of requestAnimationFrame, which is required for IE < 10. You should include it yourself.

Example

All-in-one example:

  import animate, {
    interpolateTaggedNumbers as interpolate,
    setProperty as set,
    tag,
  } from '@cdoublev/animate'

  const bounce = t => ((0.04 - (0.04 / t)) * Math.sin(25 * t)) + 1

  animate(
    element,
    [
      {
        opacity: 1,
        transform: { value: tag`translateX(${0}px) scale(${0.5})`, interpolate },
        innerText: { set, value: 0 },
      },
      {
        opacity: 0,
        transform: { value: tag`translateX(${100}px) scale(${1})`, interpolate },
        innerText: { set, value: 100 },
      }
    ],
    { duration: 2000, easing: bounce )
      .then(() => console.log('done'))

API

    import animate from '@cdoublev/animate`

animate() is the default export of this package. It's a Function which has the following signature:

animate :: (Element -> Keyframes -> Options?|Number?) -> Animation

It also exports the following functions, which are further described later:

  • setProperty: to set a property on Element instead of Element.style (inline styles)
  • setAttribute: to set a property on Element using Element.setAttribute()
  • tag: to tag value(s) to interpolate in a tagged template
  • interpolateTaggedNumbers: to interpolate tagged Number(s) and replace them in the parsed template

Arguments

Element (required)

Element should be a reference of the DOM element whose properties should be animated.

Keyframes (required)

Keyframes defines properties and values (effects) to apply during the animation's duration.

Note: a could be any type but for most use cases, it will be a Number or a String to assign to a CSS property or to Element.innerText.

1. Canonical type (collection):

  Keyframes => [Keyframe]
  Keyframe => {
    [Property]: a,
    easing?: String|Function,
    offset?: Number|String,
  }

2. Alternative type (set):

  Keyframes => {
    [Property]: [a],
    easing?: [String|Function]|String|Function,
    offset?: [Number|String]|Number|String,
  }

Those formats are specified in the WAAPI. Learn more on MDN.

Instead of assigning a String or a Number to Property, you can use a PropertyController:

  PropertyController => {
    interpolate?: (From -> To -> Time) -> a,  // Default: `interpolateNumber`
    set?: (Element -> Property -> a) -> void, // Default: `setStyle()`
    value: a,
  }
  From => To => a

set should be one of the named exports of this package: setStyle, setProperty, or setAttribute.

setStyle (default) and setProperty will delay each write on Element or Element.style, to batch their executions and avoid style/layout recalculations. setAttribute will set an attribute such as width, but its executions will not be batched.

interpolate should be a function that returns the intermediate value at the current relative Time, which will be a Number relative to the animation's duration, starting from 0 and ending at 1.

interpolateNumber (default) interpolates a Number assigned to value, eg. the value of opacity. The named exports tag and interpolateTaggedNumbers can be used to tag and interpolate Number(s) nested in a tagged template whose result is assigned to value, eg. tag`translateY(${200}px)`.

Note: a function to interpolate hexadecimal values may be provided later.

Options or duration (optional)

Options is either a Number representing the animation's duration (in milliseconds), or an Object containing one or more timing properties.

See the list of features at the top of the page, and learn more on MDN.

Instead of providing a String for easing, you can provide your own function whose type should be easing :: Time -> Number, and which is supposed to return 0 when Time is 0, and 1 when Time is 1.

If not defined, Options will default to 0.

Return value

Animation

See the list of features at the top of the page, and learn more on MDN.

Instead of using finished (Promise), you can directly use then() to chain a callback at the end of the animation. Note that it will be repeated each time Animation.playState becomes finished, eg. after repeating the execution of Animation.play() or Animation.reverse().

Chaining animations and cancel their executions in a React Component:

  import React from 'react'
  import animate from '@cdoublev/animate'

  const Component = () => {

    const animation = React.useRef({})
    const element = React.useRef()

    React.useEffect(
      () => {

        animation.current = animate(element, /*keyframes*/, 1000)
          .then(() => animation.current = animate(element, /*keyframes*/, 1000))

        return () => {
          if (animation.current.playState === 'running') {
            animation.current.cancel()
          }
        }
      }
    [animation])

    return <div ref={element}></div>
  }

@cdoublev/react-utils provides useAnimateCustom(), which is a custom hook that conveniently abstracts the above effect.

TODO

  • Performances: measure and improve
  • Fix: handle 'steps()' easing function

About

A lightweight polyfill of (the Web Animations API) Element.animate() with extra features.

Topics

Resources

License

You can’t perform that action at this time.