Curva Animada com Bezier

Antes de tudo..
Esse artigo é destinado a quem gosta de matemática e quem gosta de animação usando códigos. Caso você seja um programador e tenha curiosidade, recomendo olhar o código antes no final do artigo e depois voltar ao inicio e ir lendo com calma, assim acho que vai ficar mais interessante de ler.
Parte matemática da coisa
O que é a Curva Bezier
A Curva Bézier é uma fórmula para criar uma curva entre dois pontos. Porém ela irá precisar de um terceiro ponto que definira o arco da curva. Vou explicar primeiro os elementos da fórmula até chegar na conclusão do que precisa para recriar ela no papel.
A curva vai se formando ao longo de um tempo, esse tempo é calculado usando porcentagem. Por exemplo, a curva vai ser formada em 5s, logo 0 representa 0% e 5 representa 100%.
Na matemática porcentagem é melhor representada usando a forma decimal entre 0 e 1.
0.01 (1%) - 0.02 (2%) - 0.20 (20%) - 1 (100%).
Além da variante de tempo, a curva de Bézier precisa de 3 pontos para formar ela, o ponto inicial $A_0$, o ponto que define o arco da curva $A_1$, e o ponto que finaliza $A_2$. Esses pontos nesse exemplo vão ser pontos do eixo Y, não vamos considerar o eixo X. pois esse também vai se alterar ao longo do tempo. Vai ficar mais evidente no código em Javascript ao final do artigo.
Passo 1: Calculando $B_0$ e $B_1$
Produto é a operação de multiplicação entre dois ou mais números.
Com esses três pontos o próximo passo é achar os pontos $B_0$ e $B_1$, eles são pontos que vão se mover de acordo com o tempo $t$.
Por exemplo $B_0$, vai iniciar com o mesmo valor de $A_0$ e ao poucos vai indo até o valor de $A_1$. Ou seja, quando $t = 0$, $B_0$ vai ser igual a $A_0$, e quando $t = 1$, $B_0$ vai ser igual a $A_1$.
A fórmula $B_0$ é a soma de dois produtos, o produto $(1 - t) A_{0}$ e o produto $tA_{1}$.
$B_{0} = (1 - t) A_{0} + tA_{1}$
Produto $(1 - t) A_{0}$
$A_0$ é o ponto inicial, se o valor dele for 2, a expressão $(1 - t)$ que vai multiplicar por ele vai começar sem mudar o valor, mas ao poucos vai reduzindo o valor de 2 até chegar a 0.
Caso o ponto inicial $A_0$ tenha o valor 2, a expressão $(1 - t)$ vai reduzir ao longo do tempo de 2 para 0. Segue o exemplo a seguir:
Sendo $t = 0$, $A_0 = 2$:
$(1 - t) * A_0$ = $(1 - 0) * 2$ = $2$
Sendo $t = 0.5$, $A_0 = 2$:
$(1 - t)* A_0$ = $(1 - 0.5) * 2$ = $0.5 * 2$ = $1$
Sendo $t = 1$, $A_0 = 2$:
$(1 - t) * A_0$ = $(1 - 1) * 2$ = $1 * 2$ = $0$
Produto $t * A_1$
Enquanto $tA_1$ aos poucos vai aumentando seu valor, começando de $0$ até chegar a $A_1$.
Sendo $t = 0; A_1 = 5$:
$t*A_1$ = $0 * 5$ = $0$
Sendo $t = 0.5; A_1 = 5$:
$t*A_1$ = $0.5 * 5$ = $2.5$
Sendo $t = 1; A_1 = 5$:
$t*A_1$ = $1 * 5$ = $5$
Agora juntando as duas equações pra achar tanto $B_0$ quanto $B_1$:
Inicio da curva $t = 0$
Sendo $t = 0; A_0 = 2; A_1 = 5; A_2 = 2$:
$B_0 = (1 - t) * A_0 + tA_1$ = $(1 - 0) * 2 + 0 * 5$ = $2$
$B_1 = (1 - t) * A_1 + tA_2$ = $(1 - 0) * 5 + 0 * 2$ = $5$
Quase no meio da curva $t = 0.4$
Sendo $t = 0.4; A_0 = 2; A_1 = 5; A_2 = 2$:
$B_0 = (1 - t) A_0 + tA_1$ = $(1 -0.4) * 2 + 0.4 * 5$ = $0.6 * 2 + 2$ = $1.2 + 2$ = $3.2$
$B_1 = (1 - t) A_1 + tA_2$ = $(1 -0.4) * 5 + 0.4 * 2$ = $0.6 * 5 + 0.8$ = $3 + 0.8$ = $3.8$
Final da curva $t = 1$
Sendo $t = 1; A_0 = 2; A_1 = 5; A_2 = 2$:
$B_0 = (1 - t) A_0 + tA_1$ = $(1 - 1) * 2 + 1 * 5$ = $0 + 5$ = $5$
$B_1 = (1 - t) A_1 + tA_2$ = $(1 - 1) * 5 + 1 * 2$ = $0 + 2$ = $2$
Assim dá pra concluir que essa é um fórmula para mover tanto o ponto $B_0$ quanto o ponto $B_1$ de um ponto inicial ao um ponto final.
Passo 2: Calculando C
O ponto $C$ vai representar a curva em si, e esse ponto vai ser formado usando os outros dois pontos $B_0$ e $B_1$. A fórmula vai ser a seguinte:
$C = (1 - t) B_{0} + tB_{1}$
Logo usando os exemplos anteriores de $B_0$ e $B_1$:
$t = 0; B_0 = 2; B_1 = 5$
$C = (1 - t) B_{0} + tB_{1} = (1 - 0) * 2 + 0 * 5 = 2$
$t = 0.4; B_0 = 3.2; B_1 = 3.8$
$C = (1 - t) B_{0} + tB_{1} = (1 - 0.4)*3.2 + 0.4 * 3.8 = 0.6 * 3.2 + 0.4 * 3.8 = 1.92 + 1.52 = 3.44$
$t = 1; B_0 = 5; B_1 = 2$
$C = (1 - t) B_{0} + tB_{1} = (1 - 1) * 5 + 1 * 2 = 0 + 2 = 2$
Aqui dá pra ver que a curva começa sendo o mesmo ponto que $A_0$, vai aumentando até chegar no ponto $A_1$ e depois volta em direção ao ponto $A_2$.
A Fórmula Completa
$t$ = tempo entre 0 e 1
$A_{0}, A_{1}, A_{2}$ - pontos fixos
$B_{0}, B_{1}$ - pontos que vão se mover
$C$ - ponto que forma a curva de Bézier
$B_{0} = (1 - t) A_{0} + tA_{1}$
$B_{1} = (1 - t) A_{1} + tA_{2}$
$C = (1 - t) B_{0} + tB_{1}$
Programando
Para programar essa curva vamos usar o portal codepen: https://codepen.io/.
No código abaixo está um trecho do que eu desenvolvi usando Javascript com Canvas API do navegador.
Definindo as váriaveis
Aqui vamos definir a variável $t$ no tempo 0 e os pontos $A_0$, $A_1$ e $A_2$:
// Váriaveis para curva
let t = 0;
const A0 = { x: 30, y: 150 };
const A1 = { x: 175, y: 20 };
const A2 = { x: 350, y: 150 };
Canvas
Construindo o canvas que vai pintar a curva, caso não conheça muito sobre o Canvas API, apenas entenda que
let canvas;
let ctx;
const WIDTH = 400;
const HEIGHT = 300;
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.fillStyle = "#402050";
ctx.beginPath();
ctx.rect(0, 0, WIDTH, HEIGHT);
ctx.closePath();
ctx.fill();
ctx.moveTo(30, 150);
return setInterval(drawLine, 20);
}
init();
Desenhando a curva
Essa é a função que vai ser chamada a cada 20 milisegundos e vai desenhar os pontos da curva. Por isso é preciso calcular o ponto Cx e o ponto Cy, assim vão se tornar parametro para ctx.lineTo(Cx, Cy).
function drawLine() {
const B0x = (1 - t) * A0.x + t * A1.x;
const B1x = (1 - t) * A1.x + t * A2.x;
const Cx = (1 - t) * B0x + t * B1x;
const B0y = (1 - t) * A0.y + t * A1.y;
const B1y = (1 - t) * A1.y + t * A2.y;
const Cy = (1 - t) * B0y + t * B1y;
ctx.lineTo(Cx, Cy);
ctx.lineWidth = 2;
ctx.strokeStyle = "#FFF";
ctx.stroke();
if (t < 1) t += 0.005;
}
Conclusão
A Curva Bézier pode ter diversos pontos de controle deixando cada vez maior a fórmula, mas não mais complexa. Esse artigo me demandou alguns dias para escrever já que parece haver pouca tecnologia para sintaxe matemática nas ferramentas web.
Espero que o público-alvo também goste do artigo, pois não é algo simples de ler. É preciso prestar muita atenção e ter interesse em aprender.
Obrigado.