#
Controle avançado das animações
Nessa página da documentação, será explicado conceitos como motion values
e o hook animate
que proporcionam métodos para controlar melhor as animações.
#
Motion Values
Os motion values
são valores que designam o estado de uma animação. O estado de uma animação é definido por sua posição e velocidade.
#
useMotionValue
Esses valores podem ser utilizados pelo useMotionValue()
que apresenta métodos get()
e set()
para a posição e getVelocity()
para velocidade. Para atribuir o motion value
a um componente motion
será necessário colocá-lo na prop styles
no valor de "x" ou "y" variando com a direção escolhida.
Pode existir um Motion Value
para a direção x
e outro para a direção y
.
#
useTransform
O useTransform é um dos meios que utilizam o MotionValue
para oferecer melhor controle da animação gerada. Ele recebe uma array com possíveis entradas, definindo o intervalo de valores possíveis para os MotionValues
, e outras arrays, do mesmo tamanho das possibilidades de entradas, que irão conter as saídas para cada entrada.
"use client";
import { motion, useMotionValue, useTransform } from "framer-motion";
export default function BlocoMovel() {
const x = useMotionValue(0);
const defineXRange = () => {
if (x.get() < 0) x.set(0); // Evita o slider estourar o limite
if (x.get() > 191) x.set(191);
};
const dynamicColor = useTransform(x, [0, 191], ["#ffffff", "#21c559"]);
const dynamicOpacity = useTransform(x, [0, 191], [1, 0]);
return (
<div className="relative w-64 h-16 bg-slate-600 rounded-3xl flex items-center text-center">
<motion.p
className="absolute ml-1/2 ml-20 select-none"
style={{ opacity: dynamicOpacity }}
>
Arraste o botão
</motion.p>
<motion.div
className="w-10 h-10 ml-3 z-10 rounded-full"
drag="x"
onDrag={defineXRange}
style={{ x: x, backgroundColor: dynamicColor }}
dragConstraints={{ left: 0, right: 0 }} // Faz o bloco voltar à posição inicial quando solto
></motion.div>
</div>
);
}
Para mais informações sobre use-transform
e useTransform
, acesse Framer Motion
#
useAnimate
O hook useAnimate
permite definir um escopo de animação e nele definir o que cada elemento irá fazer em uma sequência definida. Esse hook permite criar animações mais complexas e flexiveis para uso.
O gerenciamento da animação é feito dentro de um escopo e a seleção dos elementos pode ocorrer com o uso das tags
, classes
ou ids
.
O useAnimate é mais complexo de usar que o componente motion, mas ele é uma ferramenta poderosa, pois permite o sequenciamento de animações mais complexas e criar uma animação sem precisar de conhecer todos os elementos de uma componente.
"use client";
import { useAnimate, stagger, motion } from "framer-motion";
import { useState } from "react";
export default function Menu() {
const [scope, animate] = useAnimate();
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
if (open) {
animate([
["#item", { opacity: 0, x: -300 }, { delay: stagger(0.3) }],
["#menu", { opacity: 0, x: -300 }, { duration: 2 }],
]);
} else {
animate([
["#menu", { opacity: 1, x: 0 }, { duration: 2 }],
["#item", { opacity: 1, x: 0 }, { delay: stagger(0.3) }],
]);
}
};
const exampleArray = [1, 2, 3, 4];
return (
<div ref={scope}>
<button onClick={handleClick}>Clicke!</button>
<motion.div
className="bg-slate-600 flex-col p-4 w-48"
id="menu"
initial={{ opacity: 0, x: -300 }}
>
{exampleArray.map((num) => {
return (
<motion.p
className="text-center bg-slate-300 item"
key={num}
id="item"
initial={{ opacity: 0, x: -300 }}
>
{num}
</motion.p>
);
})}
</motion.div>
</div>
);
}
#
Extras
#
Componentes
- LazyMotion: Permite diminuir o pacote inicial do Framer Motion e carregar "partes" do pacote quando for utilizar na página.
- Reorder: Componente útil para criar sequências de elementos animadas que podem ser ordenadas pelo usuário.
#
Motion Values
- useVelocity: Permite utilizar a velocidade ou acelereção de um componente para manipular alguma característica da animação.
- useSpring: Pode ser utilizado para criar movimentações do tipo mola.