Back

Entendendo Motion Values no Framer Motion

Um guia completo sobre como usar Motion Values para criar animações avançadas no Framer Motion.

Entendendo Motion Values no Framer Motion

O Framer Motion é uma biblioteca poderosa para criar animações em React. Um dos seus conceitos mais importantes é o de Motion Values. Vamos explorar em detalhes o que são Motion Values e como podemos usá-los para criar animações incríveis.

O que são Motion Values?

Motion Values são objetos que rastreiam o estado e a velocidade de valores em animação. Eles são o coração de como o Framer Motion gerencia internamente as animações.

Criando Motion Values

Para criar um Motion Value, usamos o hook useMotionValue:

1
import { useMotionValue } from "framer-motion"
2
3
function MinhaComponente() {
4
const x = useMotionValue(0)
5
return <motion.div style={{ x }} />
6
}

O valor passado para useMotionValue (neste caso, 0) é o estado inicial do Motion Value.

Vantagens de usar Motion Values

Ao criar Motion Values manualmente, você pode:

  1. Definir e obter seus estados.
  2. Passar para múltiplos componentes para sincronizar o movimento entre eles.
  3. Encadear Motion Values usando o hook useTransform.
  4. Atualizar propriedades visuais sem disparar o ciclo de renderização do React.
  5. Inscrever-se para receber atualizações.

Trabalhando com Motion Values

Atualizando valores

Você pode atualizar um Motion Value usando o método set:

1
x.set(100)

Isso não dispara uma re-renderização do React.

Lendo valores

Para ler o valor atual de um Motion Value, use o método get:

1
const valorAtual = x.get() // Retorna 100

Obtendo velocidade

Para Motion Values numéricos, você pode obter a velocidade atual:

1
const velocidade = x.getVelocity()

Injetando Motion Values em componentes

Você pode injetar Motion Values em componentes motion assim:

1
// Para componentes HTML
2
<motion.div style={{ x }} />
3
4
// Para componentes SVG
5
<motion.circle cx={cx} />

Respondendo a mudanças

Você pode adicionar ouvintes a Motion Values usando o método onChange:

1
useEffect(() => {
2
const unsubscribe = x.onChange(latest => {
3
console.log("O valor de x mudou para:", latest)
4
})
5
6
return unsubscribe
7
}, [])

Compondo Motion Values

O Framer Motion fornece hooks para compor MotionValues, como useSpring e useTransform.

Exemplo com useTransform

1
const y = useTransform(x, latest => latest * 2)
2
3
// Ou mapeando ranges
4
const xInput = [-100, 0, 100]
5
const opacidadeOutput = [0, 1, 0]
6
const opacidade = useTransform(x, xInput, opacidadeOutput)

Métodos avançados

jump(novoValor)

O método jump define o MotionValue de uma forma que quebra a continuidade dos valores anteriores:

1
const x = useSpring(0)
2
x.jump(10)

isAnimating()

Retorna true se o valor está atualmente em animação:

1
if (x.isAnimating()) {
2
console.log("x está animando")
3
}

stop()

Para a animação atual:

1
x.stop()

Eventos

Você pode se inscrever em vários eventos de um Motion Value:

1
x.on("change", latest => console.log(latest))
2
x.on("animationStart", () => console.log("Animação iniciada"))
3
x.on("animationComplete", () => console.log("Animação completa"))

Exemplo prático

Vamos criar um componente que usa Motion Values para controlar a opacidade baseada na posição:

1
import { motion, useMotionValue, useTransform, useEffect } from "framer-motion"
2
3
export const ComponenteInterativo = () => {
4
const x = useMotionValue(0)
5
const y = useMotionValue(0)
6
const opacity = useMotionValue(1)
7
8
useEffect(() => {
9
function atualizarOpacidade() {
10
const maxXY = Math.max(Math.abs(x.get()), Math.abs(y.get()))
11
const novaOpacidade = 1 - (maxXY / 100)
12
opacity.set(Math.max(0, Math.min(1, novaOpacidade)))
13
}
14
15
const unsubscribeX = x.on("change", atualizarOpacidade)
16
const unsubscribeY = y.on("change", atualizarOpacidade)
17
18
return () => {
19
unsubscribeX()
20
unsubscribeY()
21
}
22
}, [])
23
24
return (
25
<motion.div
26
drag
27
style={{ x, y, opacity, width: 100, height: 100, background: "blue" }}
28
/>
29
)
30
}

Experimente você mesmo:

import React from 'react';
import { motion, useMotionValue } from "framer-motion";

export default function ComponenteInterativo() {
const x = useMotionValue(0);
const y = useMotionValue(0);
const opacity = useMotionValue(1);

React.useEffect(() => {
  const updateOpacity = () => {
    const maxXY = Math.max(Math.abs(x.get()), Math.abs(y.get()));
    const newOpacity = 1 - (maxXY / 100);
    opacity.set(Math.max(0, Math.min(1, newOpacity)));
  };

  const unsubscribeX = x.onChange(updateOpacity);
  const unsubscribeY = y.onChange(updateOpacity);

  return () => {
    unsubscribeX();
    unsubscribeY();
  };
}, [x, y, opacity]);

return (
  <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
    <motion.div
      drag
      style={{
        x,
        y,
        opacity,
        width: 100,
        height: 100,
        background: "oklch(73.65% .124 266)",
        borderRadius: '10px',
        cursor: 'grab'
      }}
    />
  </div>
);
}

Neste exemplo, criamos um quadrado arrastável cuja opacidade diminui conforme ele é movido para longe do centro.

Conclusão

Motion Values são uma ferramenta poderosa no Framer Motion que permitem um controle fino sobre as animações. Eles oferecem uma maneira eficiente de gerenciar o estado de animação e criar interações complexas sem sacrificar o desempenho. Com a prática, você poderá criar animações incrivelmente fluidas e responsivas em suas aplicações React.