Kinetic typography com expressões
Kinetic type de qualidade não é texto com keyframes. É texto que tem uma lógica: responde a um número, uma duração, um ritmo, um estado. Quando você constrói isso com expressões, o texto se torna um sistema, não uma animação fixa.
Texto que muda de escala baseado em valor
Útil para placar, contador de progresso, slide de dados: o número maior deveria visualmente tomar mais espaço.
// em Scale do text layerctrl = thisComp.layer("[CONTROLS]");val = ctrl.effect("Valor")("Slider");
minScale = 60;maxScale = 180;minVal = 0;maxVal = 100;
normalized = (val - minVal) / (maxVal - minVal);normalized = Math.max(0, Math.min(1, normalized)); // clamp
scaleFactor = minScale + (maxScale - minScale) * normalized;[scaleFactor, scaleFactor]Texto que muda de cor baseado em valor
Três layers sobrepostos (verde, amarelo, vermelho) com opacity controlada por expressão:
// em layer VERDE:ctrl = thisComp.layer("[CONTROLS]");val = ctrl.effect("Valor")("Slider");(val >= 70) ? 100 : (val >= 40) ? (val - 40) / 30 * 100 : 0
// em layer AMARELO:(val < 40 || val > 70) ? 0 : (val < 55) ? (val - 40) / 15 * 100 : (70 - val) / 15 * 100
// em layer VERMELHO:(val <= 40) ? 100 : (val <= 70) ? (70 - val) / 30 * 100 : 0Source Text com expressão numérica
// número inteiroctrl = thisComp.layer("[CONTROLS]");val = ctrl.effect("Contador")("Slider");Math.round(val).toString()// com padding de zeros (001, 045, 100)n = Math.round(val);padded = (n < 10) ? "00" + n : (n < 100) ? "0" + n : n.toString();padded// porcentagem com decimalval.toFixed(1) + "%"Timer formatado em Source Text
ctrl = thisComp.layer("[CONTROLS]");totalSec = Math.round(ctrl.effect("Segundos")("Slider"));
mins = Math.floor(totalSec / 60);secs = totalSec % 60;
minStr = (mins < 10) ? "0" + mins : mins.toString();secStr = (secs < 10) ? "0" + secs : secs.toString();
minStr + ":" + secStrAnimação sincronizada com áudio
- Importe o arquivo de áudio
- Animation > Keyframe Assistant > Convert Audio to Keyframes
- Um nulo “Audio Amplitude” é criado com Left Channel, Right Channel, Both Channels
- Use esses valores como controladores
// escala reagindo ao áudioaudioLayer = thisComp.layer("Audio Amplitude");amplitude = audioLayer.effect("Both Channels")("Slider");
normalized = Math.min(amplitude / 80, 1); // amplitude típica: 0 a 80scale = 90 + 70 * normalized;[scale, scale]// com suavização temporal (evita jitter)audioLayer = thisComp.layer("Audio Amplitude");lookback = 0.05;samples = 5;smoothed = 0;
for (i = 0; i < samples; i++) { t = time - (lookback * i / samples); smoothed += audioLayer.effect("Both Channels")("Slider").valueAtTime(t);}smoothed /= samples;
scale = 90 + 70 * Math.min(smoothed / 80, 1);[scale, scale]Loop de texto com array de strings
// alterna entre diferentes textos em looptextos = ["Branding", "Motion", "Identity", "Design", "Story"];duracao = 2.5; // segundos por texto
idx = Math.floor(time / duracao) % textos.length;textos[idx]Fonte variável com expressão (AE 2023+)
// weight que oscila suavementebaseWeight = 400;variation = 300;oscillation = Math.sin(time * 2 * Math.PI * 0.5); // 0.5 HzbaseWeight + variation * (oscillation * 0.5 + 0.5) // de 400 a 700// weight proporcional a sliderctrl = thisComp.layer("[CONTROLS]");val = ctrl.effect("Intensidade")("Slider"); // 0 a 100
minWeight = 300;maxWeight = 900;minWeight + (maxWeight - minWeight) * (val / 100)Contador com easing manual
// easing cúbico out no próprio Source TextstartVal = 0;endVal = 1250;startTime = 1.0;endTime = 4.0;
t = (time - startTime) / (endTime - startTime);t = Math.max(0, Math.min(1, t));
eased = 1 - Math.pow(1 - t, 3);currentVal = startVal + (endVal - startVal) * eased;Math.round(currentVal).toString()Texto que reage à posição de um nulo
// layer "[CURSOR]" como controlador de posiçãocursorLayer = thisComp.layer("[CURSOR]");cursorPos = cursorLayer.transform.position;
compCenter = [thisComp.width / 2, thisComp.height / 2];dx = cursorPos[0] - compCenter[0];dy = cursorPos[1] - compCenter[1];dist = Math.sqrt(dx * dx + dy * dy);maxDist = 400;
proximity = 1 - Math.min(dist / maxDist, 1);scale = 80 + 40 * proximity;[scale, scale]Boas práticas
Sempre use um layer de controle centralizado. Sliders em um único nulo permitem ajustar toda a peça sem tocar em expressões individuais.
Separe lógica de apresentação. A expressão calcula o valor, o layer exibe. Não misture formatação de texto com cálculos complexos no Source Text.
Teste com valores extremos. Se o slider pode ir de 0 a 100, teste com -10 e 150 também. Sua expressão precisa de Math.max/Math.min para não quebrar.