React-Move Animation Library

6.5.0 · active · verified Sun Apr 19

React-Move is a highly performant, data-driven animation library for React applications, supporting animations for HTML, SVG, and React-Native elements. Currently stable at version 6.5.0, it targets React 16.3 and above, focusing on a minimal bundle size (3.5kb gzipped). The library provides fine-grained control over animation properties like delay, duration, and easing, along with lifecycle events for 'start', 'interrupt', and 'end'. A key differentiator is its flexible approach to interpolation; while it handles numeric interpolation by default, it allows integration with libraries like `d3-interpolate` for complex types such as colors, paths, and SVG transforms. Major versions often align with React's lifecycle method changes, with a commitment to API stability between major releases. It ships with full TypeScript support, making it well-suited for modern web development. While v5.x provides backward compatibility for older React versions, v6.x is recommended for React 16.3+ to leverage a smaller bundle size by omitting the `react-lifecycles-compat` polyfill.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates animating a list of SVG circle nodes using `NodeGroup`. It includes dynamic data updates, entry/update/exit animations, and utilizes `d3-interpolate` for advanced SVG transform interpolation.

import React, { useState } from 'react';
import { NodeGroup } from 'react-move';
import { interpolate, interpolateTransformSvg } from 'd3-interpolate';

interface DataItem {
  name: string;
  x: number;
  y: number;
  transform: string;
}

const AnimatedNodes: React.FC = () => {
  const [data, setData] = useState<DataItem[]>([
    { name: 'a', x: 0, y: 0, transform: 'translate(0,0) scale(1)' },
    { name: 'b', x: 50, y: 50, transform: 'translate(50,50) scale(1)' },
  ]);

  const updateData = () => {
    setData(prevData => prevData.map(d => ({
      ...d,
      x: Math.random() * 180 + 10,
      y: Math.random() * 180 + 10,
      transform: `translate(${Math.random() * 100},${Math.random() * 100}) scale(${0.5 + Math.random() * 1.5})`
    })));
  };

  return (
    <div>
      <button onClick={updateData} style={{ marginBottom: '10px' }}>Animate Nodes</button>
      <svg width="200" height="200" style={{ border: '1px solid #eee' }}>
        <NodeGroup
          data={data}
          keyAccessor={(d: DataItem) => d.name}
          start={(data: DataItem) => ({
            x: data.x,
            y: data.y,
            transform: data.transform,
            opacity: 0,
          })}
          enter={(data: DataItem) => ([
            {
              opacity: [1],
              timing: { duration: 500 },
            },
            {
              x: [data.x],
              y: [data.y],
              transform: [data.transform],
              timing: { duration: 500 },
            }
          ])}
          update={(data: DataItem) => ({
            x: [data.x],
            y: [data.y],
            transform: [data.transform],
            opacity: [1],
            timing: { duration: 500, ease: 'easeCubicOut' },
          })}
          leave={() => ([
            {
              opacity: [0],
              timing: { duration: 300 },
            },
            {
              x: [0],
              y: [0],
              timing: { duration: 300 },
            }
          ])}
          interpolation={(begValue, endValue, attr) => {
            if (attr === 'transform') {
              return interpolateTransformSvg(begValue, endValue);
            }
            return interpolate(begValue, endValue);
          }}
        >
          {nodes => (
            <g>
              {nodes.map(({ key, data: item, state }) => (
                <circle
                  key={key}
                  cx={state.x}
                  cy={state.y}
                  r={10}
                  fill="steelblue"
                  opacity={state.opacity}
                  transform={state.transform}
                />
              ))}
            </g>
          )}
        </NodeGroup>
      </svg>
    </div>
  );
};

export default AnimatedNodes;

view raw JSON →