Los handles usan un solo vocabulario. Una llamada directa aplica un corte en el cursor actual sin avanzar el tiempo; la misma llamada bajo la propiedad animate describe un Anim que solo entra en la línea de tiempo al pasarlo a scene.play(...).

dot.move_to(1.25, 1).fill(BLUE)
scene.play([dot.animate.move_to(5, 1).fill(RED)])

“Inmediato” no significa modificar un objeto ya compilado: registra un corte reversible en el cursor, y los seeks anteriores conservan el estado anterior. Construir, configurar o descartar un Anim no cambia la visibilidad, el estado ni el cursor.

Un Anim contiene un solo efecto (fade_in, write, indicate…) o una combinación de destinos de propiedad (move_to, fill, opacity…) que comparten duración, easing y retraso. Encadenar un efecto después de un destino de propiedad o de otro efecto, como dot.animate.move_to(1, 0).fade_in(), o un destino después de un efecto, como dot.animate.fade_in().move_to(1, 0), lanza ValueError; combina animaciones separadas con parallel(). Los modificadores de tiempo y de trazo (duration, easing, stroke_width…) sí se encadenan con cualquier efecto. Cada Anim es de un solo uso. pulse, wave, highlight, focus, cancel, reveal, brace y annotate sobre una selección de texto (text["parte"].animate.pulse()) están en Texto.

Destinos de propiedad

Encadena varios destinos en el mismo Anim: se interpolan a la vez desde el estado que el objeto tenga al empezar el clip.

scene.play([
  circle.animate
    .move_to(2, 0.5)
    .scale_by(1.4)
    .fill(BLUE)
    .stroke(WHITE, 0.06)
    .opacity(0.8)
    .duration(1.5)
    .easing(Easing.SMOOTH)
])

Los destinos absolutos de posición, rotación, escala y opacidad aceptan un ScalarSource: un número, Parameter, Variable, Computed o scene.time. Bajo .animate, una fuente se evalúa al inicio efectivo del clip (incluidos retrasos y secuencias) y queda congelada durante la interpolación. En el setter directo, en cambio, la fuente enlaza el canal desde el cursor: otra fuente lo reemplaza y un número lo termina con un corte reversible. Mientras un canal está enlazado, anima la fuente o fija antes el canal con un número; las animaciones que lo escriben lanzan un error.

phase = scene.viz.parameter(0.0)
height = computed(lambda x: x * x, inputs=[phase])
dot.move_to(phase, height)                      # enlazado
scene.play(phase.animate.set(2).duration(2))
dot.move_to(2, 4)                               # fija el canal
scene.play(dot.animate.move_to(other).opacity(0.5))
MÉTODOAnim.move_tomove_to(x: ScalarSource, y: ScalarSource, anchor: Anchor | None = None) -> Anim | move_to(reference: Drawable) -> Anim | move_to(point: AnchorPoint) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
x, yScalarSourceobligatorioPosición de destino.
anchorAnchor | str | NoneNonePunto del objeto que llega a (x, y); None usa el centro, salvo en un Text, que llega donde lo pondría Text.move_to(x, y): su primera línea base centrada en el punto, o su centro visual si tiene varias líneas. Un Anchor o su nombre, como "top_left".
reference / pointDrawable | AnchorPointobligatorioObjeto o punto de anclaje de la misma escena, resuelto al inicio del clip; no lo sigue después.
Devuelve: Anim — Movimiento a una posición absoluta.
Ejemplo
from gaanim import Easing, Anchor, BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
rect = scene.geometry.rect(1.25, 0.75).fill(BLUE).stroke(WHITE, 0.025).move_to(-1.5, 0)
scene.play([rect.animate.move_to(1, 0, anchor=Anchor.TOP_RIGHT).duration(0.9).easing(Easing.SMOOTH)])
scene.render()
animation preview
MÉTODOAnim.shift_byshift_by(dx: float, dy: float) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
dxfloatobligatorioDesplazamiento horizontal.
dyfloatobligatorioDesplazamiento vertical.
Devuelve: Anim — Movimiento relativo.
Ejemplo
from gaanim import Easing, BLUE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
circle = scene.geometry.circle(0.5).fill(BLUE).move_to(-1, 0)
scene.play([circle.animate.shift_by(2, 0).duration(1.0).easing(Easing.spring(stiffness=90, damping=12))])
scene.render()
animation preview
MÉTODOAnim.path_arcpath_arc(angle: float) -> Anim
Curva el move_to o shift_by de este Anim en un arco circular en lugar de la línea recta. Sin un destino de traslación lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
anglefloatobligatorioGiro del arco en radianes; positivo es antihorario.
Devuelve: Anim — El mismo movimiento, por un arco.
Ejemplo
scene.play(ball.animate.move_to(4, 0).path_arc(math.pi / 3))
MÉTODOAnim.move_alongmove_along(target: Drawable, *, orient: bool = False, rotate_offset: float = 0.0, start: float = 0.0, end: float = 1.0) -> Anim
Muestrea el contorno por longitud de arco real. Con .easing(Easing.LINEAR) la velocidad es uniforme. Con orient=True la rotación sigue la tangente, así un avión apunta hacia donde vuela; sin él, rotación y escala no cambian.
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawableobligatorioObjeto cuyo contorno se recorre: círculo, rectángulo, curva, polilínea… Se muestrea su geometría de mundo. Una arrow o curved_arrow sólida se recorre por su eje, de la cola a la punta.
orientboolFalseGira el objeto con la tangente del camino.
rotate_offsetfloat0.0Radianes que se suman a la tangente al orientar.
start, endfloat0.0, 1.0Tramo recorrido, en fracciones de longitud de arco en [0, 1]. start > end lo recorre al revés; valores iguales o fuera de rango lanzan ValueError.
Devuelve: Anim — Traslación a lo largo del camino.
Ejemplo
from gaanim import Easing, BLACK, BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background=BLACK)
circle = scene.geometry.circle(0.75).stroke(BLUE, 0.04).no_fill().move_to(0, 0)
dot = scene.geometry.dot(0.1).fill(WHITE).move_to(0.75, 0)
scene.play([dot.animate.move_along(circle).duration(2.0).easing(Easing.LINEAR)])
scene.render()
animation preview
MÉTODOAnim.scale_toscale_to(factor: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
factorScalarSourceobligatorioEscala uniforme absoluta.
Devuelve: Anim — Cambio de escala.
Ejemplo
scene.play(badge.animate.scale_to(1.5).duration(0.4))
MÉTODOAnim.scale_byscale_by(factor: float) -> Anim
Escala alrededor del pivote del objeto; cámbialo con with_pivot(x, y).
Parámetros
NombreTipoPredeterminadoDescripción
factorfloatobligatorioMultiplica la escala actual: mayor que 1 agranda y menor que 1 encoge.
Devuelve: Anim — Cambio de escala relativo.
Ejemplo
from gaanim import Easing, BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
icon = scene.geometry.circle(0.45).fill(BLUE).stroke(WHITE, 0.025).move_to(0, 0)
scene.play([icon.animate.scale_by(1.8).duration(0.7).easing(Easing.spring(stiffness=90, damping=12))])
scene.render()
animation preview
MÉTODOAnim.rotate_torotate_to(radians: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
radiansScalarSourceobligatorioRotación absoluta alrededor de Z, en radianes.
Devuelve: Anim — Giro hasta un ángulo.
Ejemplo
scene.play(needle.animate.rotate_to(1.2))
MÉTODOAnim.skew_toskew_to(x: float, y: float) -> Anim
Interpola el sesgo alrededor del pivote, como Drawable.skew_to; fija el pivote antes con with_pivot(x, y).
Parámetros
NombreTipoPredeterminadoDescripción
xfloatobligatorioCorte horizontal de destino, sin unidades.
yfloatobligatorioCorte vertical de destino, sin unidades.
Devuelve: Anim — Sesgo hasta los factores dados.
Ejemplo
scene.play(frame.animate.skew_to(0.15, 0).duration(0.4))
MÉTODOAnim.matrix_tomatrix_to(matrix: tuple[tuple[float, float], tuple[float, float]]) -> Anim
Anima hasta una transformación lineal 2D alrededor del pivote, como Drawable.matrix_to. Se descompone en giro, sesgo y escala, que se interpolan juntos. Lanza ValueError con una matriz no finita o no invertible.
Parámetros
NombreTipoPredeterminadoDescripción
matrixtuple[tuple[float, float], tuple[float, float]]obligatorioFilas ((a, b), (c, d)) de la transformación lineal de destino.
Devuelve: Anim — Transformación hasta la matriz dada.
Ejemplo
scene.play(face.animate.matrix_to(((0.87, 0), (-0.5, 1))).duration(0.6))
MÉTODOAnim.rotate_byrotate_by(radians: float) -> Anim
Gira alrededor del pivote del objeto: el que fija with_pivot o, sin él, el centro de su caja en las figuras declaradas con coordenadas de escena, como line, polygon o curved_arrow_arc. Para una bisagra o una órbita, fija el pivote antes con with_pivot(x, y). Un giro de cualquier tamaño, incluidas varias vueltas, sigue un solo easing durante toda la duración y el pivote queda fijo.
Parámetros
NombreTipoPredeterminadoDescripción
radiansfloatobligatorioÁngulo relativo en radianes; positivo es antihorario.
Devuelve: Anim — Giro relativo.
Ejemplo
from gaanim import BLUE, Scene
from math import pi
scene = Scene(frame=(16, 9), background="#0f172a")
arm = scene.geometry.rect(1, 0.175).fill(BLUE).move_to(0.5, 0).with_pivot(0, 0)
scene.play([arm.animate.rotate_by(pi/2).duration(0.9)])
scene.render()
animation preview
MÉTODOAnim.pivotpivot(x: float, y: float) -> Anim
Hace que el rotate_by(...) ya encadenado gire alrededor de (x, y) en lugar del pivote del objeto, sin cambiar ese pivote para animaciones posteriores. Llámalo después de rotate_by; en animaciones sin giro 2D no tiene efecto. Para fijar el pivote de forma duradera usa Drawable.with_pivot(x, y).
Parámetros
NombreTipoPredeterminadoDescripción
x, yfloatobligatorioPunto de giro en unidades de escena.
Devuelve: Anim — El mismo Anim.
Ejemplo
import math
from gaanim import Easing, BLACK, WHITE, Scene
scene = Scene(frame=(16, 9), background=BLACK)
dot = scene.geometry.dot(0.125).fill(WHITE).move_to(0.75, 0)
scene.play([dot.animate.rotate_by(math.tau).pivot(0, 0).duration(1.5).easing(Easing.LINEAR)])
scene.render()
animation preview
MÉTODOAnim.about_pointabout_point(x: float, y: float) -> Anim
Alias de Anim.pivot: arm.animate.rotate_by(pi / 2).about_point(0, 0).
Parámetros
NombreTipoPredeterminadoDescripción
x, yfloatobligatorioPunto de giro en unidades de escena.
Devuelve: Anim — El mismo Anim.
MÉTODOAnim.opacityopacity(value: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
valueScalarSourceobligatorioOpacidad de destino, limitada a [0, 1].
Devuelve: Anim — Cambio de opacidad.
Ejemplo
scene.play([box.animate.opacity(0.35).duration(0.6)])
MÉTODOAnim.fillfill(color: Paint) -> Anim
Los gradientes del mismo tipo interpolan su geometría y sus paradas normalizadas; un color sólido puede pasar a un gradiente y al revés. Tipos de gradiente incompatibles (lineal y radial) lanzan ValueError. Tras no_fill(), el relleno aparece desde transparente. En un Text, cada glifo interpola desde su color actual, así que los fragmentos de color propio convergen al destino. En una Primitive3D cambia el color base de su Material3D y exige un color sólido. Ver Temas y colores.
Parámetros
NombreTipoPredeterminadoDescripción
colorPaintobligatorioColor o Brush de destino.
Devuelve: Anim — Cambio de relleno.
Ejemplo
paint = Brush.linear([BLUE, GOLD], start=(-1, 0), end=(1, 0))
scene.play(circle.animate.fill(paint).duration(1.5))
MÉTODOAnim.strokestroke(color: Paint, width: float) -> Anim
La pintura se interpola como en fill. Tras no_stroke(), el trazo aparece desde transparente y crece desde ancho cero. En un Text cambia el contorno de cada glifo sin tocar sus rellenos. No existe en Primitive3D.
Parámetros
NombreTipoPredeterminadoDescripción
colorPaintobligatorioColor o Brush del trazo.
widthfloatobligatorioAncho del trazo en unidades lógicas.
Devuelve: Anim — Cambio de trazo.
Ejemplo
scene.play(square.animate.stroke(GOLD, 0.08))
MÉTODOAnim.stroke_widthstroke_width(value: float) -> Anim
En un Anim de propiedades anima el ancho del trazo. En write, create, uncreate, unwrite o draw_border_then_fill fija el ancho del trazo dibujado.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioAncho del trazo en unidades lógicas.
Devuelve: Anim — El mismo Anim.
Ejemplo
scene.play(ring.animate.stroke_width(0.12))
scene.play(ring.animate.uncreate().stroke_width(0.05))
MÉTODOAnim.setset(value: float) -> Anim
Anima un Parameter o una Variable; todo lo que depende de ellos se actualiza en cada fotograma.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioValor finito de destino.
Devuelve: Anim — Cambio del valor.
Ejemplo
theta = scene.viz.parameter(0.0)
scene.play(theta.animate.set(3.14).duration(2))
MÉTODOAnim.cropcrop(x: float, y: float, width: float, height: float, *, normalized: bool = False) -> Anim
Anima qué parte de una Image o un Video se ve dentro de su marco fijo. Un rectángulo inválido o un objeto que no es un medio lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
x, y, width, heightfloatobligatorioRectángulo de la fuente, en píxeles desde la esquina superior izquierda.
normalizedboolFalseInterpreta el rectángulo como fracciones del tamaño original.
Devuelve: Anim — Recorte animado.
Ejemplo
photo = scene.media.image("assets/cover.png").frame(6, 3.4, fit="cover")
scene.play(photo.animate.crop(0.25, 0.25, 0.5, 0.5, normalized=True).duration(1.2))
MÉTODOAnim.fill_levelfill_level(level: float) -> Anim
Anima un relleno creado con scene.geometry.fill_level. Si el nivel está enlazado a una fuente, lanza ValueError: anima la fuente o fija antes un número con set_fill_level.
Parámetros
NombreTipoPredeterminadoDescripción
levelfloatobligatorioNivel normalizado en [0, 1].
Devuelve: Anim — Cambio de nivel.
Ejemplo
drop = scene.geometry.circle(1.2).no_fill().stroke(WHITE, 0.04)
water = scene.geometry.fill_level(drop, "#38bdf8", 0.0)
scene.play([water.animate.fill_level(0.72).duration(1.4)])

Anim.custom sustituye todos los destinos por una función propia; está en Animaciones personalizadas. Los efectos animables glow, blur, shadow y trim están en Efectos.

Entradas y salidas

Una entrada programada mantiene oculto el objeto antes de empezar, también si se declaró después de otras animaciones o dentro de un grupo, y durante la transición que abre su segmento. Son entradas:

  • por opacidad: fade_in y fade_in_from;
  • por trazo: create, write y draw_border_then_fill;
  • por escala desde cero: grow_from_center, grow_from_point, grow_from_edge, grow_arrow y spin_in_from_nothing;
  • de texto: typewriter y reveal.

Las demás animaciones (move_to, scale_to, indicate…) parten del estado visible del objeto: si no debe verse antes, empieza con una entrada o dale opacity(0) y anímala con animate.opacity(1). Las salidas (fade_out, uncreate, unwrite, shrink_to_center) lo dejan oculto al terminar.

MÉTODOAnim.fade_infade_in() -> Anim
Lleva la opacidad de 0 a la que el objeto tenía declarada o fijada, o a la que tenía antes de un fade_out: opacity(0.3).hidden() termina en 0.3. Un objeto declarado con opacity(0) termina en 1.
Devuelve: Anim — Aparición por opacidad.
Ejemplo
from gaanim import BLUE, GOLD, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
title = scene.text("Fade").fill(WHITE).move_to(0, 0.5)
box = scene.geometry.rect(1.5, 0.625).fill(BLUE).move_to(0, -0.5)
scene.play([title.animate.fade_in().duration(0.5)])
scene.play([box.animate.opacity(0.35).duration(0.6)])
scene.play([title.animate.fade_out().duration(0.4)])
scene.render()
animation preview
MÉTODOAnim.fade_outfade_out() -> Anim
Devuelve: Anim — Desaparición por opacidad.
MÉTODOAnim.fade_in_fromfade_in_from(direction: Direction, distance: float = 0.48) -> Anim
Empieza invisible y desplazado, y llega a su sitio mientras aparece.
Parámetros
NombreTipoPredeterminadoDescripción
directionDirectionobligatorioLado desde el que entra: Direction.UP, DOWN, LEFT, RIGHT o una diagonal.
distancefloat0.48Distancia recorrida hasta su posición.
Devuelve: Anim — Entrada con desplazamiento.
Ejemplo
from gaanim import Direction, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
caption = scene.text("Enters from below").fill(WHITE).move_to(0, 0)
scene.play([caption.animate.fade_in_from(Direction.DOWN, distance=0.6).duration(0.8)])
scene.render()
animation preview
MÉTODOAnim.writewrite(*, by: Literal["grapheme", "word", "line", "part"] = "grapheme", order: Literal["forward", "reverse", "center", "random"] = "forward", stagger: Optional[float] = None, brush: Literal["pen", "chalk"] = "pen", seed: int = 0) -> Anim
Dibuja los contornos y luego los rellena, como el Write de Manim. Cada pieza (un glifo, una forma, un miembro de un grupo) ocupa su parte de la animación, escalonada por stagger, y la curva (lineal por defecto) se aplica al avance de cada pieza. En la primera mitad de su parte la pieza traza su contorno, un tramo de Bézier tras otro y sus contornos en orden, centrado y de un 0,25 % del alto del cuadro, en el color de su trazo (el de su relleno si no tiene). En la segunda mitad el contorno pasa a su aspecto propio: aparece el relleno y el trazo toma su ancho, o desaparece. Sin duración, dura 1 s con menos de 15 piezas y 2 s con más; scene.play(duration=...) la sigue fijando. Sin stagger, el retardo entre piezas es el de Manim, min(4 / piezas, 0.2); agrupada con by por palabras, líneas o partes es min(4 / grupos, 1), así que hasta cuatro grupos se escriben uno tras otro. Los descendientes reactivos siguen ocultos hasta la animación y conservan el progreso al regenerarse. La segmentación es la de text.words, text.lines y text.parts. Después de un destino de propiedad o de otro efecto lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
by"grapheme" | "word" | "line" | "part""grapheme"En un texto, qué unidades empiezan juntas: grafemas, palabras, líneas explícitas o partes semánticas. La puntuación se une a su vecina.
order"forward" | "reverse" | "center" | "random""forward"Orden de los grupos: hacia delante, al revés, desde el centro hacia fuera o en una permutación aleatoria que fija seed.
staggerfloat | NoneNoneRetardo relativo entre grupos; None lo adapta al número de grupos.
brush"pen" | "chalk""pen""chalk" dibuja el objeto como tiza en una pizarra durante toda la escena, como Drawable.chalk(seed).
seedint0Semilla del orden "random" y del temblor y el grano de la tiza.
Devuelve: Anim — Escritura trazo a trazo.
Ejemplo
from gaanim import Scene, part
scene = Scene(frame=(16, 9), background="#0f172a")
# Grouping is resolved by the specialized Text API.
eq = scene.text("$", part("energy", "E"), " = ", part("mass", "m"), " ", part("speed", "c^2"), "$").move_to(0, 0)
scene.play([eq.animate.write(by="part", stagger=0.08).duration(1.4)])
scene.render()
animation preview

Con brush="chalk" la fórmula se escribe como en una pizarra:

from gaanim import WHITE, Scene
scene = Scene(frame=(16, 9), background="#1f3a2e")
eq = scene.text.equation("E = m c^2").fill(WHITE).scale_to(2)
scene.play([eq.animate.write(brush="chalk", seed=3).duration(1.5)])
scene.render()
animation preview
MÉTODOAnim.unwriteunwrite() -> Anim
Borra como el Unwrite de Manim: write al revés, desde la última pieza. Cada pieza vuelve primero a su contorno y luego el contorno se recoge hasta su inicio. Dura lo que duraría write.
Devuelve: Anim — La escritura al revés.
Ejemplo
from gaanim import GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
formula = scene.text("$E = m c^2$").fill(GOLD).move_to(0, 0)
scene.play([formula.animate.write().duration(1.0)])
scene.play([formula.animate.unwrite().duration(0.7)])
scene.render()
animation preview
MÉTODOAnim.createcreate() -> Anim
Dibuja el contorno durante el primer 70 % de la duración y funde el relleno de las formas cerradas en el 30 % final. El ancho del trazo no cambia; si el objeto no tiene contorno, usa uno temporal de 0.03 unidades. Los caminos abiertos usan toda la duración para el trazo. El easing predeterminado es Easing.DOUBLE_SMOOTH. En una malla 3D, crece desde el centro mientras aparece. A diferencia de write, no sigue el orden de los glifos.
Devuelve: Anim — Trazado progresivo seguido del relleno.
Ejemplo
from gaanim import Easing, BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
circle = scene.geometry.circle(1).fill(BLUE).stroke(WHITE, 0.04).move_to(0, 0)
scene.play([circle.animate.create().duration(1.0).easing(Easing.SMOOTH)])
scene.play([circle.animate.uncreate().duration(0.6)])
scene.render()
animation preview
MÉTODOAnim.uncreateuncreate() -> Anim
Devuelve: Anim — El trazado al revés: borra el objeto.
MÉTODOAnim.draw_border_then_filldraw_border_then_fill() -> Anim
Dibuja el borde y luego inunda el interior; queda bien en formas rellenas.
Devuelve: Anim — Primero el contorno, después el relleno.
Ejemplo
from gaanim import BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
rect = scene.geometry.rect(1.75, 1).fill(BLUE).stroke(WHITE, 0.04).move_to(0, 0)
scene.play([rect.animate.draw_border_then_fill().duration(1.3)])
scene.render()
animation preview
MÉTODOAnim.with_pen_tipwith_pen_tip() -> Anim
En write, create y draw_border_then_fill, dibuja una punta de pluma en el extremo de cada trazo mientras se traza, como una escritura a mano: un punto del color del trazo (o del relleno, si la forma no tiene trazo) que desaparece cuando el trazo está completo. Un trazo con puntas propias (tip(...)) las conserva; las demás animaciones lo ignoran.
Devuelve: Anim — El mismo Anim.
Ejemplo
from gaanim import WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
path = scene.geometry.path([(-1.5, 0), (0, 0.5), (1.5, 0)]).no_fill().stroke(WHITE, 0.04)
scene.play([path.animate.write().with_pen_tip().duration(1.4)])
scene.render()
animation preview
MÉTODOAnim.grow_from_centergrow_from_center() -> Anim
Aparición desde el centro de la caja; útil para gráficas e insignias.
Devuelve: Anim — Crecimiento desde escala cero.
Ejemplo
# Visualization uses immutable ChartSpec batches.
from gaanim import Easing, Axis, BLUE, ChartSpec, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
spec = ChartSpec({"x": [0, 1, 2], "value": [18, 42, 31]}) \
  .mark("bar").encode(x="x", y="value") \
  .axes(x=Axis.category(["Q1", "Q2", "Q3"]), y=Axis.linear(0, 50))
chart = scene.viz.chart(spec)
scene.play([chart.layer("marks").animate.grow_from_center().duration(0.7).easing(Easing.spring(stiffness=90, damping=12))])
scene.play([chart.layer("marks").animate.shrink_to_center().duration(0.5)])
scene.render()
animation preview
MÉTODOAnim.shrink_to_centershrink_to_center() -> Anim
Devuelve: Anim — Reducción hasta escala cero hacia el centro.
MÉTODOAnim.grow_from_edgegrow_from_edge(direction: Direction) -> Anim
Usa la caja en su posición final: Direction.DOWN fija el punto medio del borde inferior, así una barra sube desde su base, y Direction.custom(x, y) fija el punto correspondiente de la caja. Termina en la posición y el tamaño declarados. Easing predeterminado: Easing.SMOOTH.
Parámetros
NombreTipoPredeterminadoDescripción
directionDirectionobligatorioLado de la caja que queda fijo; una diagonal fija una esquina.
Devuelve: Anim — Crecimiento desde un borde.
Ejemplo
from gaanim import BLUE, CYAN, GOLD, Direction, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
bars = [scene.geometry.rect(1.2, h).fill(c).move_to(x, h / 2 - 2) for x, h, c in [(-3, 2.5, BLUE), (-1.4, 4, CYAN), (0.2, 3, BLUE)]]
badge = scene.geometry.circle(0.9).fill(GOLD).move_to(4, 1.5)
scene.play([bar.animate.grow_from_edge(Direction.DOWN).duration(0.8) for bar in bars])
scene.play([badge.animate.grow_from_point(2.5, 0).duration(0.6)])
scene.render()
animation preview
MÉTODOAnim.grow_from_pointgrow_from_point(x: float, y: float) -> Anim
Como grow_from_center, pero con un punto fijo arbitrario, por ejemplo el origen de un globo. Coordenadas no finitas lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
x, yfloatobligatorioPunto de la escena que queda fijo.
Devuelve: Anim — Crecimiento desde un punto.
MÉTODOAnim.grow_arrowgrow_arrow() -> Anim
La cola queda fija y la punta recorre el eje de la flecha, recto o curvo en curved_arrow y curved_arrow_arc. La cabeza aparece con sus proporciones durante la primera longitud de cabeza y luego conserva su tamaño mientras el cuerpo se alarga; el grosor no cambia nunca. Un scene.geometry.connector crece por su polilínea viva, pasando por cada punto via, mientras sus extremos siguen a sus referencias. Cualquier otro objeto, o una flecha deformada por una transformación, usa create(); en un trazo con tip(...) la punta viaja con el extremo que crece. Easing predeterminado: Easing.SMOOTH. En una selección de texto lanza TypeError.
Devuelve: Anim — Crecimiento de una flecha desde la cola.
Ejemplo
from gaanim import Anchor, CYAN, GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
straight = scene.geometry.arrow(-5, 1, 0, 1, head_length=0.4, head_width=0.34, body_width=0.08).fill(CYAN).stroke(CYAN, 0.02)
curved = scene.geometry.curved_arrow(-5, -1.5, 0, -1.5, 1.2, head_length=0.4, head_width=0.34, body_width=0.08).fill(GOLD).stroke(GOLD, 0.02)
box = scene.geometry.rect(1.6, 1.0).no_fill().stroke(CYAN, 0.03).move_to(4.5, 2.2)
link = scene.geometry.connector((1.5, 0.6), box.anchor_point(Anchor.BOTTOM), via=[(4.5, 0.6)]).fill(GOLD)
scene.play([straight.animate.grow_arrow().duration(1.2), curved.animate.grow_arrow().duration(1.2), link.animate.grow_arrow().duration(1.2)])
scene.render()
animation preview
MÉTODOAnim.spin_in_from_nothingspin_in_from_nothing() -> Anim
Una entrada juguetona para estrellas e iconos.
Devuelve: Anim — Entrada girando desde escala cero.
Ejemplo
from gaanim import Easing, GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
star = scene.geometry.star(5, 0.69, 0.325).fill(GOLD).move_to(0, 0)
scene.play([star.animate.spin_in_from_nothing().duration(0.9).easing(Easing.spring(stiffness=90, damping=12))])
scene.render()
animation preview
MÉTODOAnim.show_passing_flashshow_passing_flash(*, time_width: float = 0.2) -> Anim
Como con create(), el objeto queda oculto antes del destello (salvo que una animación de trazo anterior lo muestre) y vuelve a ocultarse cuando la ventana sale por el final. Para un pulso sobre una línea visible, dibuja una segunda línea encima.
Parámetros
NombreTipoPredeterminadoDescripción
time_widthfloat0.2Longitud de la ventana visible, como fracción del camino, en (0, 1].
Devuelve: Anim — Una ventana que recorre el trazo.
Ejemplo
pulse = scene.geometry.line(-5, 0, 5, 0).stroke(CYAN, 0.06)
scene.wait(0.5)                                                  # oculta
scene.play(pulse.animate.show_passing_flash(time_width=0.3).duration(1.0))
scene.wait(0.5)                                                  # oculta

Las animaciones de trazo de un mismo objeto (create, write, trim, show_passing_flash) comparten el canal effect, así que no pueden solaparse dentro de un play. El error indica las dos animaciones, sus tramos y el tipo de objeto; encadénalas con sequence o combínalas en una sola. Dos tramos que solo se tocan no se consideran solapados.

Énfasis

MÉTODOAnim.indicateindicate(*, color: Optional[ColorLike] = None, scale_factor: float = 1.2) -> Anim
Crece desde su centro visual la primera mitad y vuelve la segunda, mientras se tiñe de color y recupera su color; el objeto termina en su estado.
Parámetros
NombreTipoPredeterminadoDescripción
colorColorLike | NoneNoneTinte de los rellenos y trazos sólidos; sin él, el "accent" del tema, o su "foreground" si el objeto ya tiene el color del acento.
scale_factorfloat1.2Cuánto crece. Debe ser positivo.
Devuelve: Anim — Un salto con resaltado.
Ejemplo
from gaanim import BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
key = scene.geometry.circle(0.4).fill(BLUE).stroke(WHITE, 0.025).move_to(-0.625, 0)
wrong = scene.geometry.cross(0.35).stroke(WHITE, 0.04).move_to(0.75, 0)
scene.play([key.animate.indicate().duration(0.7)])
scene.play([wrong.animate.wiggle().duration(0.5)])
scene.render()
animation preview
MÉTODOAnim.wigglewiggle(amplitude: float = 0.1, count: int = 3) -> Anim
Sacude el objeto de lado a lado y lo deja donde estaba. Útil para señalar una respuesta incorrecta.
Parámetros
NombreTipoPredeterminadoDescripción
amplitudefloat0.1Desplazamiento a cada lado, en unidades de escena. No negativo.
countint3Vaivenes a derecha e izquierda. Al menos 1.
Devuelve: Anim — Una sacudida breve.
MÉTODOAnim.circumscribecircumscribe(*, color: Optional[ColorLike] = None, width: Optional[float] = None, padding: Optional[Padding] = None, corner_radius: float = 0.08) -> Anim
Dibuja un marco vivo alrededor del objeto la primera mitad y lo borra desde su inicio la segunda, como el Circumscribe de Manim: es flash_around(time_width=1.0). Fuera de la animación el marco es invisible. El Anim se reproduce sobre el marco, no sobre el objeto.
Parámetros
NombreTipoPredeterminadoDescripción
colorColorLike | NoneNoneColor del marco; sin él, el trazo del tema.
widthfloat | NoneNoneGrosor del marco; necesita color.
paddingfloat | Padding | NoneNoneSeparación del marco a los límites; 0,12 por defecto.
corner_radiusfloat0.08Radio de las esquinas.
Devuelve: Anim — Un contorno que rodea el objeto.
Ejemplo
scene.play(result.animate.circumscribe().duration(1.0))
MÉTODOAnim.flashflash(*, color: Optional[ColorLike] = None, width: Optional[float] = None, lines: int = 12, length: float = 0.3, gap: float = 0.15) -> Anim
Los rayos son un objeto vivo nuevo, repartidos desde la derecha y que siguen al objeto si se mueve. Cada uno se dibuja hacia fuera y luego se va desde su extremo interior; fuera de la animación son invisibles. El Anim se reproduce sobre los rayos, no sobre el objeto.
Parámetros
NombreTipoPredeterminadoDescripción
colorColorLike | NoneNoneColor de los rayos; sin él, el trazo del tema.
widthfloat | NoneNoneGrosor de los rayos; necesita color.
linesint12Número de rayos, de 1 a 64.
lengthfloat0.3Largo de cada rayo. Positivo.
gapfloat0.15Distancia entre el círculo que contiene los límites del objeto y el inicio de los rayos. No negativa.
Devuelve: Anim — Un destello de líneas alrededor del objeto.
Ejemplo
scene.play(star.animate.flash().duration(0.6))
MÉTODOAnim.blinkblink(count=3) -> Anim
Cada parpadeo es un fundido rápido a nada y de vuelta, y dura medio segundo: la duración por defecto es 0.5 * count, y duration fija el ciclo completo. Al final el objeto vuelve a verse.
Parámetros
NombreTipoPredeterminadoDescripción
countint3Cuántas veces parpadea; menos de 1 lanza ValueError.
Devuelve: Anim — Apaga y enciende el objeto count veces.
Ejemplo
scene.play(caret.animate.blink(3))
MÉTODOAnim.broadcastbroadcast(count=4, max_scale=3.0, lag=0.2) -> Anim
Cada onda es una copia del objeto, colocada donde está cuando empieza la animación, que crece hasta max_scale mientras se desvanece. duration cubre todas las ondas. El objeto no cambia y las copias son invisibles fuera de su onda. Valores fuera de rango lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
countint4Ondas, de 1 a 64.
max_scalefloat3.0Tamaño final de cada onda respecto al objeto; al menos 1.
lagfloat0.2Cuánto tarda cada onda en salir tras la anterior, como fracción de una onda.
Devuelve: Anim — Ondas concéntricas que salen del objeto.
Ejemplo
from gaanim import PINK, Scene

scene = Scene(frame=(16, 9), background="#0f172a")
pin = scene.geometry.dot(0.2).fill(PINK)
scene.play([pin.animate.broadcast(count=4, max_scale=4.0, lag=0.25).duration(2.0)])
scene.render()
animation preview
MÉTODOAnim.flash_aroundflash_around(*, color=None, width=None, padding=None, corner_radius=0.08, time_width=0.4) -> Anim
El marco es un contorno vivo nuevo (como Geometry.surrounding_rect) que sigue los límites del objeto y es invisible fuera del destello. La animación devuelta se reproduce sobre el marco. Sirve también sobre un TextSelection: texto["palabra"].animate.flash_around().
Parámetros
NombreTipoPredeterminadoDescripción
color, widthColorLike | None, float | NoneNoneReestilizan el marco; un ancho necesita un color. Sin ellos usa el trazo del tema.
paddingPadding | None0.12Separación entre el objeto y el marco.
corner_radiusfloat0.08Radio de las esquinas.
time_widthfloat0.4Longitud de la ventana brillante, como fracción del contorno, en (0, 1].
Devuelve: Anim — Una ventana brillante que recorre un marco alrededor del objeto.
Ejemplo
scene.play(line["importante"].animate.flash_around(color=PINK, width=0.04).duration(1.2))
MÉTODOAnim.flash_underflash_under(*, color=None, width=None, gap=0.06, overhang=0.04, time_width=0.5) -> Anim
La línea es un subrayado vivo nuevo, tan ancho como el objeto, invisible fuera del destello. Valores fuera de rango lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
color, widthColorLike | None, float | NoneNoneComo en flash_around.
gapfloat0.06Distancia de la línea bajo el objeto.
overhangfloat0.04Cuánto sobresale la línea a cada lado.
time_widthfloat0.5Longitud de la ventana brillante, en (0, 1].
Devuelve: Anim — Una ventana brillante que recorre una línea bajo el objeto.
Ejemplo
scene.play(line["resalta"].animate.flash_under(color=GOLD, width=0.05).duration(1.0))
MÉTODOFx.spotlightscene.fx.spotlight(target, *, dim=0.7, padding=None, corner_radius=0.1) -> Anim
Un velo negro con un hueco vivo alrededor del objetivo (sigue al objetivo si se mueve) llega a dim a mitad de la animación y vuelve a nada; duration fija el ciclo entero y una curva como Easing.SMOOTH lo deja oscurecido al final. Con varios objetivos hay un hueco alrededor de cada uno, y los que se solapan se unen; para iluminar la caja conjunta, agrúpalos. La animación devuelta se reproduce sobre el velo. Una secuencia vacía, un dim fuera de rango o un objetivo de otra escena lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawable | TextSelection | SequenceobligatorioLo que queda iluminado. Con una secuencia, cada objetivo tiene su hueco.
dimfloat0.7Opacidad máxima del velo negro, en (0, 1].
paddingPadding | None0.2Separación entre el objetivo y el borde del hueco.
corner_radiusfloat0.1Radio de las esquinas del hueco.
Devuelve: Anim — Un velo con un hueco que se oscurece y vuelve.
Ejemplo
from gaanim import BLUE, WHITE, Scene

scene = Scene(frame=(16, 9), background="#0f172a")
title = scene.text("Un título", role="title").fill(WHITE).move_to(0, 2.4)
card = scene.geometry.rounded_rect(4, 2.2, 0.25).fill("#1e293b").stroke(BLUE, 0.03).move_to(0, -0.6)
scene.play([scene.fx.spotlight(card, dim=0.8).duration(2.0)])
scene.render()
animation preview
MÉTODODrawable.animated_boundaryanimated_boundary(colors, *, cycle_rate=0.5, width=0.04, padding=None, corner_radius=0.08) -> Drawable
El marco es un objeto nuevo, visible desde el principio, que sigue los límites del objeto; anímalo como cualquier otro (fade_in, fade_out) para que aparezca o desaparezca. El color es función pura del tiempo, así que los seeks y la exportación coinciden con la reproducción. Menos de dos colores, un width no positivo o un cycle_rate no finito lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
colorsSequence[ColorLike]obligatorioAl menos dos colores; el último se mezcla de nuevo con el primero.
cycle_ratefloat0.5Vueltas a la lista de colores por segundo, desde el cursor de la línea de tiempo.
widthfloat0.04Ancho del trazo, en unidades de escena.
paddingPadding | None0.12Separación entre el objeto y el marco.
corner_radiusfloat0.08Radio de las esquinas.
Devuelve: Drawable — Un marco vivo con el trazo que cambia de color.
Ejemplo
border = card.animated_boundary([BLUE, PURPLE, CYAN], cycle_rate=0.5)
scene.wait(2)

Texto

Estas animaciones solo existen sobre un Text completo; en otro objeto lanzan TypeError. Se evalúan de forma nativa a partir del tiempo del clip, así que los seeks, las capturas y la exportación coinciden. El Text que escriben queda oculto hasta que empiezan, así las filas de un stagger esperan sin verse. Las selecciones, anotaciones y transiciones de fórmulas están en Texto.

MÉTODOAnim.typewritertypewriter(cps: float = 18.0, cursor: Optional[str] = "▍", blink: float = 2.0, jitter: float = 0.2, seed: int = 0, keep_cursor: bool = True) -> Anim
Vacía el Text y lo vuelve a escribir un grafema por pulsación, con el diseño final: los glifos aparecen en su sitio y nada se reacomoda. El cursor sigue al último grafema, también entre líneas. Sin duración explícita dura hasta la última pulsación (unos grafemas / cps segundos); .duration(...) reescala el ritmo. Valores inválidos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
cpsfloat18.0Pulsaciones por segundo; positivo.
cursorstr | None"▍"Cadena dibujada tras el último grafema; None o "" para ninguno. Los caracteres de bloque (de ▏ a █) son rectángulos exactos, independientes de la fuente.
blinkfloat2.0Parpadeos por segundo del cursor en reposo; 0 lo deja fijo. Mientras escribe está fijo.
jitterfloat0.2Cada intervalo se multiplica por un factor en [1 - jitter, 1 + jitter]; debe estar en [0, 1).
seedint0Semilla del ritmo de pulsaciones.
keep_cursorboolTrueMantiene el cursor al terminar; False lo quita.
Devuelve: Anim — Escritura tecla a tecla, con tiempo lineal.
Ejemplo
from gaanim import CYAN, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
prompt = scene.text("gaanim render", role="code").fill(CYAN).move_to(-3, 0)
scene.play([prompt.animate.typewriter(cps=18, cursor="▍")])
scene.wait(0.4)
scene.play([prompt.animate.backspace(6)])
scene.play([prompt.animate.retype("gaanim export --from clímax")])
scene.wait(0.6)
scene.render()
animation preview
MÉTODOAnim.backspacebackspace(count: Optional[int] = None, cps: float = 24.0) -> Anim
El cursor retrocede con cada borrado; un Text sin cursor recibe el parpadeante predeterminado. Dura count / cps por defecto.
Parámetros
NombreTipoPredeterminadoDescripción
countint | NoneNoneGrafemas que se borran desde el final, como máximo los visibles; None borra todos.
cpsfloat24.0Borrados por segundo; positivo.
Devuelve: Anim — Borrado tecla a tecla.
MÉTODOAnim.retyperetype(text: str, cps: float = 18.0, jitter: float = 0.2, seed: int = 0) -> Anim
Conserva el prefijo que comparte con el texto visible, borra lo demás y escribe el resto con el estilo y el origen del Text. Después el Text muestra text, pero su contenido declarado (tamaño de layout, selecciones text[...]) no cambia.
Parámetros
NombreTipoPredeterminadoDescripción
textstrobligatorioTexto plano nuevo, no vacío.
cps, jitter, seedfloat, float, int18.0, 0.2, 0Como en typewriter.
Devuelve: Anim — Borrado hasta el prefijo común y escritura del resto.
MÉTODOAnim.scramblescramble(charset: str = "upper", reveal_delay: float = 0.3, speed: float = 20.0, seed: int = 0) -> Anim
Cada grafema muestra glifos aleatorios del juego de caracteres, centrados en su celda final, y después se asienta de izquierda a derecha. El ancho del texto final queda reservado, así que no salta. Dura reveal_delay más 0.05 s por grafema (al menos 0.6 s).
Parámetros
NombreTipoPredeterminadoDescripción
charsetstr"upper""upper", "lower", "digits", "hex", "symbols" o una cadena literal como "01".
reveal_delayfloat0.3Segundos que todas las posiciones cambian antes de que se asiente la primera.
speedfloat20.0Cambios de glifo por segundo; positivo.
seedint0Semilla de la elección de glifos.
Devuelve: Anim — Revelado por decodificación, con tiempo lineal.
Ejemplo
from gaanim import GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
label = scene.text("LAUNCH SEQUENCE", role="title").fill(GOLD).move_to(0, 0)
scene.play([label.animate.scramble(charset="upper", reveal_delay=0.3, speed=20)])
scene.wait(0.4)
scene.play([label.animate.scramble_to("LANZAMIENTO", charset="01")])
scene.render()
animation preview
MÉTODOAnim.scramble_toscramble_to(text: str, charset: str = "upper", reveal_delay: float = 0.3, speed: float = 20.0, seed: int = 0) -> Anim
Los glifos actuales desaparecen al empezar y cada posición de text se decodifica en el diseño de text.
Parámetros
NombreTipoPredeterminadoDescripción
textstrobligatorioTexto plano nuevo, no vacío.
charset, reveal_delay, speed, seedComo en scramble.
Devuelve: Anim — Decodificación hacia un texto nuevo.
MÉTODOAnim.revealreveal(style: Optional[Literal["slide_up", "slide_down", "fade", "scale", "blur"]] = None, *, by: Literal["grapheme", "word", "line", "part"] = "line", mask: bool = True, stagger: float = 0.06) -> Anim
Con "slide_up" cada unidad sube una altura de fila desde detrás de su máscara, así que también funciona en la exportación SVG. Sin máscara, los deslizamientos recorren menos y aparecen por opacidad. .easing(...) suaviza cada unidad (cúbica de salida por defecto) y la duración cubre toda la cascada. Ver Texto para la versión sobre selecciones.
Parámetros
NombreTipoPredeterminadoDescripción
style"slide_up" | "slide_down" | "fade" | "scale" | "blur" | NoneNoneEstilo de entrada; None es "slide_up".
by"grapheme" | "word" | "line" | "part""line"Unidad que entra de una vez.
maskboolTrueLos estilos de deslizamiento salen de detrás de una máscara vectorial recortada a su fila.
staggerfloat0.06Segundos entre unidades.
Devuelve: Anim — Revelado unidad a unidad.
Ejemplo
title = scene.text("Una idea\npor línea", role="title")
scene.play(title.animate.reveal(by="line", style="slide_up", stagger=0.06))
scene.play(title.animate.conceal(by="line", style="slide_up"))
MÉTODOAnim.concealconceal(style: Literal["slide_up", "slide_down", "fade", "scale", "blur"] = "slide_up", *, by: Literal["grapheme", "word", "line", "part"] = "line", mask: bool = True, stagger: float = 0.06) -> Anim
La salida que corresponde a reveal: las unidades se van en orden de lectura desde el reposo y quedan ocultas. Los deslizamientos conservan la dirección del revelado. Aceleran al salir (cúbica de entrada por defecto).
Parámetros
NombreTipoPredeterminadoDescripción
style, by, mask, stagger"slide_up", "line", True, 0.06Como en reveal.
Devuelve: Anim — Salida unidad a unidad.
MÉTODOAnim.blur_inblur_in(sigma: float = 0.3, *, by: Literal["grapheme", "word", "line", "part"] = "grapheme", stagger: float = 0.02) -> Anim
Cada unidad pierde el desenfoque y aparece con una curva de salida. Un sigma o stagger negativo lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
sigmafloat0.3Desenfoque inicial en unidades de escena.
by"grapheme" | "word" | "line" | "part""grapheme"Unidad que entra de una vez.
staggerfloat0.02Segundos entre unidades.
Devuelve: Anim — Entrada desde un desenfoque transparente.
Ejemplo
title = scene.text("Enfoque", role="title")
scene.play(title.animate.blur_in(sigma=0.3, by="grapheme", stagger=0.02))
MÉTODOAnim.trackingtracking(value: float) -> Anim
Los glifos se desplazan por la línea base sin rehacer el diseño, anclados según la alineación del texto. Easing predeterminado: suave. Se combina con animaciones que no mueven glifos, como blur_in; scene.play rechaza dos animaciones simultáneas que escriben el mismo canal de glifos.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioEspacio extra entre glifos vecinos, en unidades de escena; 0 restaura el original.
Devuelve: Anim — Cambio animado del espaciado.
Ejemplo
title = scene.text("ESPACIO", role="title")
title.tracking(0.4)
scene.play(title.animate.tracking(0.0).duration(1.2))
MÉTODOAnim.path_offsetpath_offset(value: float) -> Anim
Mueve un texto creado con scene.text.on_path por su trayectoria. En una trayectoria cerrada 1.0 es una vuelta completa. Cada fotograma se calcula a partir del desplazamiento, así que un seek muestra lo mismo que la reproducción. Easing predeterminado: suave; usa Easing.LINEAR para un giro constante. Un texto que no sea de on_path o un valor no finito lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioDesplazamiento a lo largo de la trayectoria, como fracción de su longitud.
Devuelve: Anim — Recorrido animado del texto por su trayectoria.
Ejemplo
ring = scene.text.on_path("GAANIM · MOTION · ", scene.geometry.circle(2.0), reverse=True)
scene.play([ring.animate.path_offset(1.0).duration(4).easing(Easing.LINEAR)])

Transformaciones

MÉTODOAnim.transform_totransform_to(target: Drawable) -> Anim
Transforma la geometría del objeto hasta la del destino. Respeta los tiempos compuestos y un relleno ausente no se inventa. Cada contorno se empareja con el sentido de recorrido y el punto de inicio que menos mueven sus puntos, así que una forma y su espejo no colapsan a mitad del morph. Un relleno o trazo con degradado se interpola hacia el del destino (posición y paradas); dos degradados de tipos distintos pasan por un color liso a mitad. De un Text a otro Text es una transición estructural: las partes con el mismo nombre viajan a su sitio, cada glifo conserva su color (también los de part()) y al terminar se muestra el destino; entre textos de Layouts distintos es un morph de forma única (ver Texto). Entre grupos o SVG importados (también una parte <g> de un SVG) el morph es pieza a pieza y en el sitio: las partes con el mismo nombre o id de SVG se emparejan, a cualquier profundidad, y las demás hojas se emparejan por forma dentro de su pareja; las hojas sobrantes del objeto se desvanecen y las del destino aparecen donde está el destino. El objeto conserva su identidad, así que sus part() siguen valiendo después. También conserva su propia opacidad: el destino es solo una plantilla, oculta durante y después del morph, así que un destino declarado con .opacity(0) no lo deja invisible. Para cambiarla mientras se transforma, reproduce un animate.opacity del mismo objeto en el mismo play.
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawableobligatorioObjeto de la misma escena cuya forma se adopta.
Devuelve: Anim — Transformación en el sitio.
Ejemplo
from gaanim import Easing, BLUE, GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
circle = scene.geometry.circle(0.525).fill(BLUE).move_to(-1.125, 0)
target = scene.geometry.rect(1.125, 0.75).fill(GOLD).move_to(1, 0)
scene.play([circle.animate.create().duration(0.6)])
scene.play([circle.animate.transform_to(target).duration(1.0).easing(Easing.spring(stiffness=90, damping=12))])
scene.render()
animation preview
MÉTODOAnim.fade_transform_tofade_transform_to(target: Drawable) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawableobligatorioObjeto de la misma escena.
Devuelve: Anim — Fundido cruzado hacia el destino.
MÉTODOAnim.replacement_transform_toreplacement_transform_to(target: Drawable) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawableobligatorioObjeto de la misma escena.
Devuelve: Anim — Transformación que termina sustituyendo el origen por el destino.
Ejemplo
scene.play(square.animate.replacement_transform_to(circle))
MÉTODOGeometry.transform_matching_shapestransform_matching_shapes(source: Drawable, target: Drawable, *, duration: float = 1.0) -> None
Empareja las piezas de origen y destino por forma, posición y color, transforma las parejas y funde el resto. Se reproduce como un scene.play: lo siguiente empieza cuando termina. El destino está oculto hasta entonces; al final se muestra y el origen se oculta, así que las animaciones siguientes del destino mueven lo que se ve.
Parámetros
NombreTipoPredeterminadoDescripción
sourceDrawableobligatorioObjeto o grupo de origen.
targetDrawableobligatorioObjeto o grupo de destino.
durationfloat1.0Segundos; finito y positivo.
Devuelve: None — Reproduce la transformación en el cursor y lo avanza duration segundos.
Ejemplo
from gaanim import GOLD, WHITE, Scene

scene = Scene(frame=(16, 9), background="#0f172a")
e1 = scene.text("$E = m c$").fill(WHITE).scale_to(1.3)
e2 = scene.text("$p = m v$").fill(GOLD).scale_to(1.3)
scene.play(e1.animate.write())
scene.geometry.transform_matching_shapes(e1, e2, duration=1.2)
scene.render()
MÉTODOGeometry.transform_matchingtransform_matching(source: Drawable, target: Drawable, *, mode: str = "shapes", duration: float = 1.0) -> None
Versión general de transform_matching_shapes: al final se muestra el destino y se oculta el origen. Otro mode lanza ValueError. Para textos estructurados es preferible animate.transform_to, que es un Anim normal.
Parámetros
NombreTipoPredeterminadoDescripción
source, targetDrawableobligatorioObjetos de origen y destino.
modestr"shapes""shapes" empareja por geometría; "tex" (o "text") empareja los glifos de dos textos o ecuaciones por carácter, en orden de lectura, y vuelve a la geometría si alguno no tiene glifos.
durationfloat1.0Segundos; finito y positivo.
Devuelve: None — Reproduce la transformación en el cursor y lo avanza duration segundos.
FUNCIÓNmagic_movemagic_move(before: Drawable, after: Drawable, *, key: str | Callable[[Drawable], object] = "name", unmatched: str = "fade", duration: float | None = None) -> Anim
Los miembros de before y after con la misma clave interpolan posición, tamaño, color y forma; una pareja de grupos transforma también sus piezas, como transform_matching. Los candidatos se buscan en profundidad y un miembro con clave se mueve entero. Las claves se leen al llamar a magic_move y las repetidas se emparejan en orden de declaración. after queda oculto hasta el movimiento y lo sustituye al final, así que las animaciones siguientes continúan desde él. Sin duration dura un segundo, o la duration que reciba scene.play. Objetos de escenas distintas, el mismo objeto dos veces, una duración no positiva o un key/unmatched desconocido lanzan ValueError; una excepción de la función clave se propaga.
Parámetros
NombreTipoPredeterminadoDescripción
before, afterDrawableobligatorioEstados de origen y destino, normalmente grupos de la misma escena.
keystr | Callable[[Drawable], object]"name""name" usa los nombres de Drawable.named (una parte SVG sin nombre responde a su id); "id" usa solo los id SVG; una función recibe cada candidato y devuelve su clave, o None para buscar dentro de él.
unmatchedstr"fade""fade" funde a la vez los miembros sin pareja; "cut" los quita al empezar y muestra los nuevos al terminar.
durationfloat1.0Segundos; finito y positivo.
Devuelve: Anim — Magic move listo para scene.play.
Ejemplo
from gaanim import BLUE, GOLD, GREEN, RED, Scene, magic_move
scene = Scene(frame=(16, 9), background="#0f172a")
def board(rows):
    bars = [
        scene.geometry.rect(score, 0.6).fill(color).move_to(score / 2 - 4, 1.5 - rank).named(name)
        for rank, (name, score, color) in enumerate(rows)
    ]
    return scene.geometry.group(bars)
before = board([("ana", 5, BLUE), ("bo", 4, GOLD), ("cy", 3, RED)])
after = board([("bo", 6, GOLD), ("ana", 4.5, BLUE), ("dee", 2, GREEN)])
scene.wait(0.3)
scene.play([magic_move(before, after, key="name", unmatched="fade").duration(0.8)])
scene.wait(0.3)
scene.render()
animation preview

Animaciones personalizadas

MÉTODOAnim.customcustom(callback: Callable[[float], CustomAnimationValues], *, channels: Sequence[AnimationChannel]) -> Anim
Los valores son absolutos: position es una pareja o terna local en unidades de escena, rotation un ángulo Z en radianes, scale un factor o una terna, opacity un número entre 0 y 1, fill y stroke pinturas y stroke_width un ancho no negativo. La función se evalúa en el instante exacto al reproducir, buscar o exportar; debe ser síncrona y pura, sin modificar la escena. El progreso puede salir de [0, 1] con algunos easings. No mezcles custom y setters en un mismo Anim: usa parallel. Si falla durante la reproducción, los canales vuelven a su valor inicial y aparece un diagnóstico; la exportación falla. Los tipos AnimationChannel y CustomAnimationValues se importan desde gaanim.
Parámetros
NombreTipoPredeterminadoDescripción
callbackCallable[[float], CustomAnimationValues]obligatorioRecibe el progreso ya con easing y devuelve un diccionario con exactamente los canales declarados.
channelsSequence[AnimationChannel]obligatorioCanales que escribe: "position", "rotation", "scale", "opacity", "fill", "stroke", "stroke_width".
Devuelve: Anim — Una animación normal: admite duración, retraso, easing y composición.
Ejemplo
motion = dot.animate.custom(
    lambda alpha: {
        "position": (3 * alpha, alpha * alpha),
        "opacity": 1 - 0.5 * alpha,
    },
    channels=("position", "opacity"),
).duration(2).easing(Easing.SMOOTH)
scene.play(parallel(motion, dot.animate.fill(BLUE).duration(2)))

Keyframes y física ligera

MÉTODOAnim.keyframeskeyframes(times: Sequence[float], *, position: Optional[Sequence[Optional[tuple[float, float] | tuple[float, float, float]]]] = None, offset: Optional[Sequence[Optional[tuple[float, float] | tuple[float, float, float]]]] = None, rotation: Optional[Sequence[Optional[float]]] = None, scale: Optional[Sequence[Optional[float | tuple[float, float] | tuple[float, float, float]]]] = None, opacity: Optional[Sequence[Optional[float]]] = None, fill: Optional[Sequence[Optional[Paint]]] = None, stroke: Optional[Sequence[Optional[Paint]]] = None, values: Optional[Sequence[Optional[float]]] = None, easing: Optional[Easing | Sequence[Easing]] = None, spatial: Literal["linear", "catmull_rom"] = "linear") -> Anim
Describe un movimiento de varios tiempos sin encadenar sequence del mismo objeto, como los keyframes de GSAP o interpolate de Remotion. El easing propio del clip queda lineal para que cada parada caiga en su instante: Scene.play(easing=) no lo cambia y .easing() remapea el clip entero. Dura 1 s o lo que indique .duration(), y admite repeat y loop. Longitudes distintas, instantes que no van de 0 a 1 o valores inválidos lanzan ValueError; no se combina con otros destinos en el mismo Anim ni con settle.
Parámetros
NombreTipoPredeterminadoDescripción
timesSequence[float]obligatorioInstantes de las paradas como fracciones de la animación: empiezan en 0, terminan en 1 y crecen.
position / rotation / scale / opacity / fill / strokeSequenceNoneUn valor por instante. None conserva el valor que tiene el objeto al empezar. position es (x, y) o (x, y, z) y fija el origen del objeto, no su centro visual como move_to: coinciden en una forma creada en el origen, pero no en un SVG o un texto dibujado en otro sitio. rotation es un ángulo absoluto en radianes, scale un factor o (sx, sy[, sz]), opacity entre 0 y 1, fill y stroke pinturas.
offsetSequence[tuple | None]NoneDesplazamientos desde donde está el objeto al empezar, en lugar de posiciones: offset=[None, (3, 0), None] va 3 unidades a la derecha y vuelve, esté donde esté su dibujo. None equivale a (0, 0). No se combina con position.
valuesSequence[float | None]NoneEn Parameter.animate, los valores del parámetro en lugar de canales.
easingEasing | Sequence[Easing]NoneUn easing para todos los tramos o uno por tramo; lineal si se omite.
spatial"linear" | "catmull_rom""linear"Con "catmull_rom" la posición recorre una curva suave que pasa por las paradas, como los keyframes espaciales de After Effects.
Devuelve: Anim — Un solo clip con todas las paradas.
Ejemplo
from gaanim import CORAL, GOLD, Easing, EasingCurve, Scene
scene = Scene(frame=(16, 9))
ball = scene.geometry.circle(0.45).fill(GOLD).move_to(-5.5, -1.5)
level = scene.viz.parameter(0.4)
dot = scene.geometry.circle(0.5).fill(CORAL).move_to(4.5, 2.0)
dot.scale_to(level)
scene.play([
    ball.animate.keyframes(
        times=[0.0, 0.35, 0.7, 1.0],
        position=[None, (-2.0, 1.5), (1.0, -1.5), (5.0, -1.5)],
        scale=[1.0, 1.0, (1.35, 0.7), 1.0],
        easing=[Easing.ease_out(EasingCurve.QUADRATIC), Easing.ease_in(EasingCurve.QUADRATIC), Easing.SMOOTH],
        spatial="catmull_rom",
    ).duration(1.6),
    level.animate.keyframes(times=[0, 0.3, 1], values=[None, 1.6, 0.8], easing=Easing.SMOOTH).duration(1.6),
])
scene.render()
animation preview
MÉTODOAnim.throwthrow(velocity: float | tuple[float, float], *, gravity: float = 9.8, floor: Optional[float] = None, restitution: float = 0.55) -> Anim
Balística por tramos analíticos, como Physics2D de GSAP: un arco, rebotes cada vez más bajos y reposo cuando un rebote subiría menos de una milésima de unidad. Es una función pura del tiempo, así que cualquier seek es exacto. Si no se indica, la duración es la del lanzamiento y Scene.play(duration=) no la cambia; .duration() reproduce el mismo arco más rápido o más lento. Un segundo throw sigue desde donde reposó el primero. La física de cuerpos rígidos con colisiones queda fuera: hornéala con add_updater_fn(fixed_dt=...). Valores inválidos, empezar bajo el suelo o lanzar hacia abajo sin suelo lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
velocityfloat | tuple[float, float]obligatorio(vx, vy) en unidades por segundo; un número lanza en horizontal.
gravityfloat9.8Aceleración hacia abajo en unidades por segundo al cuadrado; positiva.
floorfloat | NoneNoneAltura en la que rebota el punto más bajo del objeto, medido al llamar a throw. Sin suelo vuela hasta volver a su altura inicial, lo que pide una velocidad hacia arriba.
restitutionfloat0.55Fracción de la velocidad que conserva cada rebote, en [0, 1).
Devuelve: Anim — El lanzamiento desde donde esté el objeto.
Ejemplo
from gaanim import GOLD, TEAL, WHITE, Scene
scene = Scene(frame=(16, 9))
scene.geometry.line(-7.5, -3.0, 7.5, -3.0).stroke(WHITE, 0.03)
ball = scene.geometry.circle(0.35).fill(GOLD).move_to(-6.5, -1.0)
coin = scene.geometry.circle(0.3).fill(TEAL).move_to(0.0, 1.0)
scene.play([
    ball.animate.throw(velocity=(3.0, 4.0), floor=-3.0, restitution=0.6),
    coin.animate.inertia(velocity=7.0, friction=2.5, snap=[0.0, 2.0, 4.0, 6.0]),
])
scene.render()
animation preview
MÉTODOAnim.inertiainertia(velocity: float | tuple[float, float], *, friction: float = 3.0, snap: Optional[Sequence[float | tuple[float, float]]] = None) -> Anim
Deceleración exponencial, como Inertia de GSAP: el objeto reposaría a velocity / friction de donde empieza y termina, en cambio, en el punto de snap más cercano a ese reposo, aunque quede detrás. Si no se indica, dura ln(1000) / friction segundos, lo que tarda en recorrer el 99,9 %. Valores inválidos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
velocityfloat | tuple[float, float]obligatorio(vx, vy) en unidades por segundo; un número desliza en horizontal.
frictionfloat3.0Frenado por segundo, positivo: la velocidad cae a 1/e cada 1 / friction segundos.
snapSequence[float | tuple[float, float]] | NoneNonePuntos de reposo: un número fija solo x y (x, y) un punto entero.
Devuelve: Anim — El deslizamiento desde donde esté el objeto.

Efectos y trazos

Estos destinos interpolan los efectos estáticos del mismo nombre de Drawable y se combinan con otros destinos de propiedad.

MÉTODOAnim.glowglow(color: Optional[ColorLike] = None, radius: float = 0.16, intensity: float = 1.0) -> Anim
Un objeto sin resplandor lo hace crecer desde intensidad cero. Valores inválidos lanzan ValueError; en una selección de texto, TypeError.
Parámetros
NombreTipoPredeterminadoDescripción
colorColor | NoneNoneColor del resplandor; None lo desvanece.
radiusfloat0.16Radio en unidades de escena.
intensityfloat1.0Intensidad.
Devuelve: Anim — Resplandor animado.
Ejemplo
scene.play(orb.animate.glow(CYAN, radius=0.5, intensity=2.0).repeat(3, yoyo=True))
MÉTODOAnim.blurblur(sigma: float = 0.04) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
sigmafloat0.04Desenfoque final; 0 termina nítido.
Devuelve: Anim — Desenfoque animado.
Ejemplo
hero.blur(0.3)
scene.play(hero.animate.blur(0.0).duration(0.6))   # entrada desde el desenfoque
MÉTODOAnim.shadowshadow(color: Optional[ColorLike] = None, x: float = 0.08, y: float = -0.08, blur: float = 0.06) -> Anim
Una sombra nueva crece desde debajo del objeto.
Parámetros
NombreTipoPredeterminadoDescripción
colorColor | NoneNoneColor de la sombra; None la desvanece. Su alfa escala la opacidad de forma continua.
x, yfloat0.08, -0.08Desplazamiento de la sombra.
blurfloat0.06Desenfoque de la sombra.
Devuelve: Anim — Sombra animada.
Ejemplo
card.shadow(BLACK, 0, -0.05, 0.05)
scene.play(card.animate.shadow(BLACK, 0, -0.25, 0.4).scale_to(1.04))   # levantar
MÉTODOAnim.trimtrim(start: Optional[float] = None, end: Optional[float] = None, offset: Optional[float] = None) -> Anim
Los valores omitidos conservan el actual. Animar offset hace viajar un segmento. El recorte también se mantiene en trazos que se regeneran en cada fotograma, como conectores, líneas entre extremos y curvas reactivas. Ver Drawable.trim.
Parámetros
NombreTipoPredeterminadoDescripción
start, endfloat | NoneNoneVentana visible del trazo, en fracciones de longitud de arco en [0, 1].
offsetfloat | NoneNoneDesplaza la ventana y da la vuelta al final del camino.
Devuelve: Anim — Recorte animado del trazo.
Ejemplo
logo.trim(end=0.0)
scene.play(logo.animate.trim(end=1.0).duration(1.2))             # dibujar
ring.trim(start=0.5, end=0.5)
scene.play(ring.animate.trim(start=0.0, end=1.0))                # desde el centro
orbit.trim(start=0.0, end=0.15)
scene.play(orbit.animate.trim(offset=1.0).duration(2))           # segmento viajero
MÉTODOAnim.dash_offsetdash_offset(offset: float) -> Anim
Anima el dash_offset de todos los trazos del objeto, incluidos los de un grupo o un texto. El trazo necesita guiones (StrokeStyle(dashes=...)). Un valor mayor lleva el patrón hacia el inicio del camino, así que animarlo hace marchar los guiones. La siguiente animación parte del valor final. Para un flujo sin fin usa Updater.dash_flow. Un valor no finito lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
offsetfloatobligatorioDesplazamiento del patrón de guiones, en unidades de escena.
Devuelve: Anim — Desplazamiento animado de los guiones.
Ejemplo
from gaanim import CYAN, Scene, StrokeStyle
scene = Scene(frame=(16, 9), background="#0f172a")
border = scene.geometry.rounded_rect(8, 4, 0.3).no_fill().stroke_style(StrokeStyle(CYAN, 0.06, dashes=[0.3, 0.2]))
scene.play([border.animate.dash_offset(2.0).duration(2)])
scene.render()
animation preview
MÉTODOAnim.countcount(count: float) -> Anim
Anima cuántas copias de un grupo creado con Geometry.repeat o Geometry.duplicate se ven. Las copias aparecen en orden desde la primera: la copia i se ve cuando el recuento supera i y la parte fraccionaria funde la siguiente, así que count(24) desde 0 construye el patrón copia a copia. La opacidad de cada copia se conserva. El máximo es el número de copias con que se creó el grupo; para hacer crecer un patrón, créalo con todas y baja antes su recuento con Drawable.count. Un valor fuera de rango, o un objeto que no sea uno de esos grupos, lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
countfloatobligatorioCopias visibles al terminar, de 0 al número de copias del grupo.
Devuelve: Anim — Recuento animado de las copias.
Ejemplo
from gaanim import GOLD, Easing, Scene
scene = Scene(frame=(16, 9), background="#0d1322")
leaf = scene.geometry.ellipse(0.12, 0.34).fill(GOLD).move_to(0, 2.4)
spiral = scene.geometry.repeat(leaf, 36, rotate=0.5, scale=0.95, about=(0, 0)).count(0)
scene.play([spiral.animate.count(36).duration(2.0).easing(Easing.LINEAR)])
scene.render()
animation preview
MÉTODOAnim.pointspoints(points: Sequence[tuple[float, float]]) -> Anim
Para fijar los vértices sin animar, usa Drawable.points. Lleva cada vértice de un polígono o una polilínea en línea recta a su nueva posición: el vértice i va a points[i]. A diferencia de transform_to no remuestrea el contorno, así que cada fotograma es la mezcla exacta de los dos y las figuras de píxel o técnicas conservan sus esquinas. Un move_to o shift posterior se sigue aplicando encima. La figura conserva su número de vértices: otro número de puntos, una figura que no sea polígono o polilínea (o que lo sea con coordenadas reactivas), o un punto no finito lanzan ValueError. Se combina con fill, move_to y los demás destinos de propiedades en un mismo Anim, y echo repite el morph en sus copias.
Parámetros
NombreTipoPredeterminadoDescripción
pointsSequence[tuple[float, float]]obligatorioPosición final de cada vértice, en las coordenadas en que se declaró la figura.
Devuelve: Anim — Morph vértice a vértice.
Ejemplo
from gaanim import Easing, Scene
# El símbolo de Gaanim: un fotograma de píxeles que avanza y deja los anteriores con echo.
FRAMES = ((8,) * 8, (6,) + (8,) * 6 + (6,), (4, 6, 8, 8, 8, 8, 6, 4))
COLORS = ("#3F37A8", "#7C6CFF", "#FFC933")

def outline(widths, cx, pixel=0.5):
    top, right, left = len(widths) * pixel / 2, [], []
    for row, width in enumerate(widths):
        y0, y1, half = top - row * pixel, top - (row + 1) * pixel, width * pixel / 2
        right += [(cx + half, y0), (cx + half, y1)]
        left += [(cx - half, y0), (cx - half, y1)]
    return right + left[::-1]

scene = Scene(frame=(16, 9), background="#1A1A1A")
symbol = scene.geometry.polygon(outline(FRAMES[0], -1)).fill(COLORS[0]).echo(2, delay=0.6, decay=1.0)
for index in (1, 2):
    scene.play([symbol.animate.points(outline(FRAMES[index], index - 1)).fill(COLORS[index]).duration(0.6).easing(Easing.LINEAR)])
scene.wait(1.0)
scene.render()
animation preview

Tiempo

MÉTODOAnim.durationduration(seconds: float) -> Anim
duration(0) es un corte: el destino se aplica de golpe en ese punto de la composición. Sirve para cambiar un valor a mitad de un sequence o de un play con delay, sin partir el bloque: sequence(a.animate.shift_by(2, 0), a.animate.opacity(0.3).duration(0), a.animate.shift_by(-2, 0)).
Parámetros
NombreTipoPredeterminadoDescripción
secondsfloatobligatorioDuración finita y no negativa.
Devuelve: Anim — El Anim configurado.
Ejemplo
scene.play(circle.animate.shift_by(3, 0).duration(1.0).delay(0.3).easing(Easing.LINEAR))
MÉTODOAnim.delaydelay(seconds: float) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
secondsfloatobligatorioEspera antes de empezar; finita y no negativa.
Devuelve: Anim — El Anim configurado.
MÉTODOAnim.easingeasing(easing: Easing) -> Anim
No se aceptan nombres en texto: usa siempre un Easing. Ver Easing.
Parámetros
NombreTipoPredeterminadoDescripción
easingEasingobligatorioPreset o resultado de una fábrica de Easing.
Devuelve: Anim — El Anim configurado.
Ejemplo
from gaanim import Easing, BLUE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
dot = scene.geometry.dot(0.125).fill(BLUE).move_to(-1.375, 0)
scene.play([dot.animate.shift_by(2.75, 0).duration(0.9).easing(Easing.spring(stiffness=90, damping=12))])
scene.play([dot.animate.shift_by(-2.75, 0).duration(0.9).easing(Easing.SMOOTH)])
scene.render()
animation preview
MÉTODOAnim.lag_ratiolag_ratio(value: float) -> Anim
Escalona los subcaminos o miembros dentro de un mismo objeto, por ejemplo los de un grupo.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioSolapamiento entre subtrazos, en [0, 1]: 0 los anima a la vez y 1 uno detrás de otro.
Devuelve: Anim — El Anim configurado.
Ejemplo
from gaanim import BLUE, WHITE, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
g = scene.geometry.group([scene.geometry.circle(0.225).fill(BLUE).move_to(-0.625,0), scene.geometry.circle(0.225).fill(BLUE).move_to(0,0), scene.geometry.circle(0.225).fill(BLUE).move_to(0.625,0)])
scene.play([g.animate.create().duration(1.0).lag_ratio(0.25)])
scene.render()
animation preview
MÉTODOAnim.repeatrepeat(count: int, *, yoyo: bool = False, delay: float = 0.0) -> Anim
duration y easing describen un ciclo. Con yoyo=True un número par de ciclos termina donde empezó y las animaciones siguientes continúan desde ahí. La duración total es count * duration + (count - 1) * delay.
Parámetros
NombreTipoPredeterminadoDescripción
countintobligatorioNúmero de ciclos, entre 1 y 10000.
yoyoboolFalseAlterna el sentido de cada ciclo.
delayfloat0.0Segundos entre ciclos; no negativo.
Devuelve: Anim — El Anim repetido.
Ejemplo
scene.play(spinner.animate.rotate_by(math.tau).duration(1.2).repeat(3))
scene.play(badge.animate.scale_to(1.08).duration(0.4).repeat(4, yoyo=True, delay=0.1))
MÉTODOAnim.looploop(mode: Literal["cycle", "pingpong", "offset"] = "cycle", *, until: float, delay: float = 0.0) -> Anim
El bucle es finito, así que los seeks y la exportación son exactos.
Parámetros
NombreTipoPredeterminadoDescripción
mode"cycle" | "pingpong" | "offset""cycle""cycle" reinicia cada ciclo, "pingpong" alterna el sentido y "offset" continúa desde donde terminó el anterior, así rotate_by o shift_by se acumulan.
untilfloatobligatorioSegundos disponibles; caben tantos ciclos completos como sea posible, al menos uno.
delayfloat0.0Segundos entre ciclos.
Devuelve: Anim — El Anim repetido.
Ejemplo
scene.play(arrow.animate.shift_by(0.3, 0).duration(0.5).loop("pingpong", until=4.0))
MÉTODOAnim.settlesettle(overshoot: float = 0.12, frequency: float = 3.0, decay: float = 6.0) -> Anim
Follow-through: al terminar el movimiento, cada propiedad animada rebasa su destino y vuelve oscilando como v * overshoot * sin(2π * frequency * t) / e^(decay * t), donde t son los segundos tras el movimiento y v su velocidad final en unidades por segundo. Si el easing termina en reposo (como smooth) se usa la velocidad media, así que un movimiento suavizado también rebota. El clip se alarga hasta que el rebote cae bajo el 0,1 % de la distancia recorrida (como mucho 10 s más) y termina exactamente en el destino; play lo espera. Va después del último ciclo de repeat o loop. Es una función pura del tiempo, así que cualquier seek es exacto. Valores negativos o no finitos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
overshootfloat0.12Segundos de rebote por unidad de velocidad final (el amp de After Effects); 0 desactiva el rebote.
frequencyfloat3.0Oscilaciones por segundo; positiva.
decayfloat6.0Amortiguación exponencial en 1/s; positiva.
Devuelve: Anim — El Anim con rebote inercial.
Ejemplo
scene.play(card.animate.move_to(0, 0).duration(0.5).settle(overshoot=0.12, frequency=3.0, decay=6.0))

Easing

Un Easing es una función de tiempo inmutable: convierte el progreso lineal del clip en el progreso que se ve. Hay presets con nombre y fábricas que validan sus argumentos; no se aceptan nombres en texto ni hay un valor de reserva silencioso. Todas rechazan números no finitos y dominios inválidos con ValueError.

CONSTANTEEasing.LINEAR / SMOOTH / DOUBLE_SMOOTH / THERE_AND_BACK / LINGERING / RUNNING_START / EXPONENTIAL_DECAY / NOT_QUITE_THEREEasing.LINEAR · Easing.SMOOTH · …: Easing
Curvas clásicas.
Ejemplo
PresetForma
LINEARVelocidad constante.
SMOOTHArranca y frena suave (3t² - 2t³). Es el easing predeterminado de muchas animaciones.
DOUBLE_SMOOTHSMOOTH aplicado dos veces: arranque y frenado más marcados. Predeterminado de create.
THERE_AND_BACKLlega al destino a mitad del clip y vuelve al inicio.
LINGERINGCurva suave de quinto grado (6t⁵ - 15t⁴ + 10t³), con extremos todavía más lentos que SMOOTH.
RUNNING_STARTRetrocede un poco antes de arrancar hacia el destino.
EXPONENTIAL_DECAYSale rápido y se acerca al destino cada vez más despacio.
NOT_QUITE_THEREComo EXPONENTIAL_DECAY, pero se queda en el 95 % del recorrido.
from gaanim import Anchor, Easing, GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
presets = [("LINEAR", Easing.LINEAR), ("SMOOTH", Easing.SMOOTH), ("DOUBLE_SMOOTH", Easing.DOUBLE_SMOOTH), ("RUNNING_START", Easing.RUNNING_START), ("EXPONENTIAL_DECAY", Easing.EXPONENTIAL_DECAY)]
moves = []
for row, (name, easing) in enumerate(presets):
    y = 2.4 - 1.2 * row
    scene.text(name, size=0.32).move_to(-3.4, y, Anchor.RIGHT)
    dot = scene.geometry.dot(0.16).fill(GOLD).move_to(-1.6, y)
    moves.append(dot.animate.move_to(6, y).duration(1.5).easing(easing))
scene.play(moves)
scene.wait(0.3)
scene.render()
animation preview
CONSTANTEEasing.SMOOTH_SPRING / GENTLE / QUICK / SNAPPY / BOUNCYEasing.SMOOTH_SPRING · Easing.GENTLE · …: Easing
Resortes perceptuales con nombre: se asientan dentro de la duración de la animación y terminan exactamente en el destino.
Ejemplo
PresetCarácter
SMOOTH_SPRINGAmortiguamiento crítico: el asentamiento más rápido sin pasarse.
GENTLESuave y sin prisa, con un sobrepaso apenas visible.
QUICKEnérgico, con un sobrepaso pequeño que se asienta pronto.
SNAPPYRápido, con un sobrepaso nítido del 20 %.
BOUNCYJuguetón, con un sobrepaso del 45 % y rebotes visibles.
scene.play(card.animate.scale_to(1.0).duration(0.6).easing(Easing.SNAPPY))
CONSTANTEEasingCurve.QUADRATIC / CUBIC / QUARTIC / QUINTIC / EXPONENTIAL / SINE / CIRCULAR / BACK / ELASTIC / BOUNCEEasingCurve.QUADRATIC · EasingCurve.CUBIC · …: EasingCurve
Familias de curvas para Easing.ease_in, ease_out y ease_in_out. QUADRATIC a QUINTIC son potencias de grado 2 a 5; EXPONENTIAL, SINE y CIRCULAR, las curvas clásicas de CSS; BACK se pasa un poco del destino, ELASTIC oscila y BOUNCE rebota.
FÁBRICAEasing.ease_inease_in(curve: EasingCurve) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
curveEasingCurveobligatorioFamilia de la curva.
Devuelve: Easing — Arranque lento y final rápido.
FÁBRICAEasing.ease_outease_out(curve: EasingCurve) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
curveEasingCurveobligatorioFamilia de la curva.
Devuelve: Easing — Arranque rápido y final lento.
FÁBRICAEasing.ease_in_outease_in_out(curve: EasingCurve) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
curveEasingCurveobligatorioFamilia de la curva.
Devuelve: Easing — Arranque y final lentos.
Ejemplo
scene.play(circle.animate.shift_by(8, 0).easing(Easing.ease_in_out(EasingCurve.CUBIC)))
scene.play(circle.animate.shift_by(-8, 0).easing(Easing.ease_out(EasingCurve.BOUNCE)))
FÁBRICAEasing.springspring(stiffness: Optional[float] = None, damping: Optional[float] = None, *, mass: float = 1.0, velocity: float = 0.0, bounce: Optional[float] = None) -> Easing
Con bounce, el resorte se describe por cómo se ve: se asienta dentro de la duración de la animación, así que duration marca el ritmo. Sin él es físico (stiffness, damping, mass) y el clip abarca cinco segundos físicos. Combinar bounce con parámetros físicos lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
stiffnessfloat | None90Rigidez física; positiva.
dampingfloat | None12Amortiguamiento físico; no negativo.
massfloat1.0Masa física; positiva.
velocityfloat0.0Velocidad inicial, en distancias por duración del clip.
bouncefloat | NoneNoneResorte perceptual: sobrepaso máximo en [0, 1); 0 es amortiguamiento crítico.
Devuelve: Easing — Un resorte que termina exactamente en el destino.
Ejemplo
scene.play(logo.animate.scale_to(1.0).duration(0.6).easing(Easing.spring(bounce=0.35)))
scene.play(logo.animate.rotate_by(1.0).easing(Easing.spring(stiffness=90, damping=12)))
FÁBRICAEasing.backback(overshoot: float = 1.70158, *, mode: Literal["in", "out", "in_out"] = "out") -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
overshootfloat1.70158Cuánto retrocede o se pasa; no negativo.
mode"in" | "out" | "in_out""out""in" retrocede al empezar, "out" se pasa al llegar y "in_out" hace las dos cosas.
Devuelve: Easing — Retroceso o sobrepaso.
FÁBRICAEasing.elasticelastic(amplitude: float = 1.0, period: float = 0.3, *, mode: Literal["in", "out", "in_out"] = "out") -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
amplitudefloat1.0Amplitud de la oscilación; al menos 1.
periodfloat0.3Periodo en fracciones del clip; positivo.
mode"in" | "out" | "in_out""out"Extremo en el que oscila.
Devuelve: Easing — Oscilación como una banda elástica.
FÁBRICAEasing.bouncebounce(strength: float = 1.0, *, mode: Literal["in", "out", "in_out"] = "out") -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
strengthfloat1.0Mezcla de una curva cúbica (0) al rebote clásico (1).
mode"in" | "out" | "in_out""out"Extremo en el que rebota.
Devuelve: Easing — Rebotes al llegar. Con strength=1 y mode="out" el objeto toca el destino por primera vez al 4/11 (≈ 0,364) de la duración y vuelve a tocarlo a 8/11, 10/11 y al final; para que el golpe caiga en un instante t, empieza la animación en t - 0.364 * duración. Con strength < 1 solo llega exactamente al final: el primer rebote se queda en 1 - 0,258 · (1 - strength) del recorrido, también a 4/11. Para un contacto en otro instante, escribe la curva con Easing.custom.
Ejemplo
scene.play(ball.animate.move_to(0, -3).duration(1.2).easing(Easing.bounce()))
scene.play(ball.animate.move_to(0, 0).easing(Easing.elastic(amplitude=1.2, period=0.4)))
scene.play(ball.animate.shift_by(3, 0).easing(Easing.back(mode="in_out")))
FÁBRICAEasing.slow_moslow_mo(linear_ratio: float = 0.7, power: float = 0.7) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
linear_ratiofloat0.7Fracción central que avanza lenta y lineal, en [0, 1].
powerfloat0.7Fuerza de la aceleración en los extremos, en [0, 1].
Devuelve: Easing — Rápido, cámara lenta, rápido.
FÁBRICAEasing.roughrough(strength: float = 1.0, points: int = 20, seed: int = 0) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
strengthfloat1.0Intensidad del temblor.
pointsint20Número de nudos aleatorios.
seedint0Semilla de los nudos.
Devuelve: Easing — Rampa temblorosa determinista, para parpadeos y glitches.
Ejemplo
scene.play(sign.animate.opacity(0.2).duration(1.0).easing(Easing.rough(strength=1, points=20, seed=4)))
scene.play(sign.animate.shift_by(4, 0).duration(1.5).easing(Easing.slow_mo(0.7, 0.7)))
FÁBRICAEasing.squishsquish(easing: Easing, start: float, end: float) -> Easing
Útil para que una animación de una lista paralela empiece más tarde o termine antes que las demás sin cambiar su duración.
Parámetros
NombreTipoPredeterminadoDescripción
easingEasingobligatorioEasing que se comprime.
start, endfloatobligatorioTramo del clip en el que actúa, con 0 <= start < end <= 1.
Devuelve: Easing — El easing solo dentro del tramo; fuera mantiene sus extremos.
Ejemplo
scene.play([
    a.animate.shift_by(8, 0).duration(2),
    b.animate.shift_by(8, 0).duration(2).easing(Easing.squish(Easing.SMOOTH, 0.5, 1.0)),
])
FÁBRICAEasing.stepssteps(count: int, jump: Literal["start", "end", "none", "both"] = "end") -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
countintobligatorioNúmero de escalones.
jump"start" | "end" | "none" | "both""end"Dónde ocurren los saltos, como en steps() de CSS.
Devuelve: Easing — Interpolación discreta.
FÁBRICAEasing.mirrormirror(easing: Easing) -> Easing
Convierte un ease_in en una curva simétrica de entrada y salida.
Parámetros
NombreTipoPredeterminadoDescripción
easingEasingobligatorioEasing de la primera mitad.
Devuelve: Easing — El easing comprimido en la primera mitad y reflejado en la segunda.
FÁBRICAEasing.there_and_backthere_and_back(pause: float = 0.0) -> Easing
Llega al destino y regresa al inicio dentro del mismo clip.
Parámetros
NombreTipoPredeterminadoDescripción
pausefloat0.0Fracción del clip que se detiene en el destino, en [0, 1].
Devuelve: Easing — Ida y vuelta.
Ejemplo
scene.play(clock.animate.rotate_by(-6.283).duration(2).easing(Easing.steps(12)))
scene.play(badge.animate.scale_to(1.3).duration(0.8).easing(Easing.there_and_back(pause=0.2)))
scene.play(badge.animate.shift_by(-6, 0).easing(Easing.mirror(Easing.ease_in(EasingCurve.QUINTIC))))
FÁBRICAEasing.cubic_beziercubic_bezier(x1: float, y1: float, x2: float, y2: float) -> Easing
Parámetros
NombreTipoPredeterminadoDescripción
x1, y1, x2, y2floatobligatorioPuntos de control, como en cubic-bezier() de CSS; x1 y x2 en [0, 1].
Devuelve: Easing — Una curva de Bézier cúbica.
FÁBRICAEasing.from_svgfrom_svg(path: str, samples: int = 256) -> Easing
El camino debe ir de x = 0 a x = 1 sin retroceder en x y quedarse con y en [-1, 2]; si no, lanza ValueError. Sirve para una curva copiada de cualquier editor.
Parámetros
NombreTipoPredeterminadoDescripción
pathstrobligatorioCamino SVG dibujado en el cuadrado unidad (x = tiempo, y = progreso).
samplesint256Muestras de la tabla interpolada.
Devuelve: Easing — La curva dibujada.
Ejemplo
scene.play(panel.animate.shift_by(8, 0).easing(Easing.cubic_bezier(0.2, 0.8, 0.2, 1.0)))
scene.play(panel.animate.shift_by(-8, 0).easing(Easing.from_svg("M0,0 C0.3,0 0.2,1.2 1,1")))
FÁBRICAEasing.customcustom(function: Callable[[float], float], samples: int = 256) -> Easing
Llama a la función samples veces, en tiempos equiespaciados, al crear el easing. El render nunca vuelve a Python, así que la previsualización, los seeks y la exportación coinciden. Los valores deben ser finitos y estar en [-1, 2] (se permite pasarse del destino); si no, lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
functionCallable[[float], float]obligatorioFunción de t en [0, 1] que devuelve el progreso.
samplesint256Muestras, en [2, 65536].
Devuelve: Easing — Una tabla interpolada linealmente.
Ejemplo
salto = Easing.custom(lambda t: 1 - abs(math.cos(3 * math.pi * t)) * (1 - t) ** 2)
scene.play(ball.animate.move_to(0, -2).duration(1.2).easing(salto))

Composición

scene.play([...]) ya reproduce una lista en paralelo. Para estructuras más ricas, estas funciones construyen un árbol inmutable, Composition, que scene.play resuelve de forma atómica: valores por defecto, tramos, solapes, conflictos de canales y destinos relativos.

FUNCIÓNparallelparallel(*items: Playable) -> Composition
Parámetros
NombreTipoPredeterminadoDescripción
itemsPlayableobligatorioUno o más Anim, medios o composiciones.
Devuelve: Composition — Todos empiezan en el mismo origen.
FUNCIÓNsequencesequence(*items: Playable, gap: float = 0.0) -> Composition
Parámetros
NombreTipoPredeterminadoDescripción
itemsPlayableobligatorioUno o más elementos.
gapfloat0.0Segundos entre pasos; un valor negativo acotado los solapa.
Devuelve: Composition — Uno detrás de otro.
Ejemplo
scene.play(
    sequence(
        title.animate.write().duration(0.8),
        parallel(
            box.animate.create(),
            stagger(label.animate.fade_in(), badge.animate.fade_in(), each=0.15),
        ),
        gap=-0.1,
    )
)
FUNCIÓNstaggerstagger(*items: Playable, each: float = 0.1, total: float | None = None, origin: StaggerOrigin | None = None, grid: Literal["auto"] | tuple[int, int] | None = None, easing: Easing | None = None, seed: int = 0) -> Composition
Sin origin ni grid, escalona por índice: total fija la duración de toda la onda y easing la acelera o frena, pero el orden sigue siendo el de la lista. Con origin o grid, el retardo crece con la distancia al origen, que es el primer elemento ("start") si solo se pasa grid. Los elementos cuya posición depende de un layout usan su índice.
Parámetros
NombreTipoPredeterminadoDescripción
itemsPlayableobligatorioElementos escalonados.
eachfloat0.1Retardo por índice, o por paso de separación con origin; no negativo.
totalfloat | NoneNoneFija la duración de toda la onda en lugar de each.
originStaggerOrigin | NoneNone"start", "end", "center", "edges" (de los bordes hacia dentro), "random" o un punto (x, y).
grid"auto" | tuple[int, int] | NoneNoneDistancias según las posiciones declaradas ("auto") o las celdas de (filas, columnas).
easingEasing | NoneNoneDa forma al reparto de retardos.
seedint0Semilla de origin="random".
Devuelve: Composition — Elementos desplazados en el tiempo.
Ejemplo
scene.play(stagger(*[d.animate.grow_from_center() for d in dots], each=0.03, origin="center"))
scene.play(stagger(*[d.animate.indicate() for d in dots], total=1.2, origin="random", seed=7))
scene.play(stagger(*[d.animate.fill(GOLD) for d in dots], each=0.05, origin=(0.0, -3.0)))
scene.play(stagger(*[d.animate.fade_out() for d in dots], total=1.0, easing=Easing.ease_out(EasingCurve.QUADRATIC)))
FUNCIÓNdistributedistribute(items: Sequence[Drawable], low: float, high: float, *, origin: StaggerOrigin | None = None, grid: Literal["auto"] | tuple[int, int] | None = None, easing: Easing | None = None, seed: int = 0) -> list[float]
Usa el mismo orden que stagger para repartir tamaños, colores u opacidades en lugar de tiempos; sin origin ni grid, el de la lista.
Parámetros
NombreTipoPredeterminadoDescripción
itemsSequence[Drawable]obligatorioObjetos que reciben un valor cada uno.
low, highfloatobligatorioRango de valores.
origin, grid, easing, seedNone, None, None, 0Como en stagger.
Devuelve: list[float] — Un valor por objeto.
Ejemplo
for dot, size in zip(dots, distribute(dots, 0.4, 1.4, origin="edges")):
    dot.scale_by(size)

Playable es la unión de todo lo que acepta scene.play (Anim, Audio, Video, VideoSegment, Lottie y Composition). Impórtala desde gaanim para anotar tus funciones; también funciona con isinstance.

from gaanim import Playable, parallel

def entrada(*items: Playable) -> Playable:
    return parallel(*items).delay(0.2)
FUNCIÓNlabellabel(name: str) -> Composition
En un sequence no ocupa un paso ni suma gap: marca dónde empieza el siguiente paso, o dónde termina el anterior si es el último. Se referencia desde Composition.insert y sus tiempos aparecen en Schedule.labels. Un nombre vacío, numérico o que empieza por <, >, +, - o = lanza ValueError. Para instantes de la línea de tiempo global, usa scene.marker.
Parámetros
NombreTipoPredeterminadoDescripción
namestrobligatorioNombre único en el árbol; se recortan los espacios.
Devuelve: Composition — Un instante con nombre y sin duración.
MÉTODOComposition.insertinsert(item: Playable, at: str | float) -> Composition
Las inserciones se colocan después de los hijos y antes de stretch, repeat y delay, que también las afectan. Una posición mal escrita lanza ValueError enseguida; una etiqueta desconocida (el error lista las definidas) o una posición antes de 0 lo lanzan en schedule() o scene.play. Un nombre exacto de etiqueta siempre gana, así que "parte-2" encuentra la etiqueta "parte-2".
Parámetros
NombreTipoPredeterminadoDescripción
itemPlayableobligatorioElemento que se añade; puede ser otro label.
atstr | floatobligatorioPosición local, con la sintaxis de la tabla.
Devuelve: Composition — Una copia; el original no cambia.
Ejemplo
atPosición
"nombre", "nombre+0.15", "nombre-0.2", "nombre+=0.15"Una etiqueta más un desplazamiento.
"<", ">", "<+0.1", ">-0.2"Inicio o final del elemento anterior: la última inserción que no es etiqueta o, si no hay, el último hijo.
"+=0.3", "-=0.3"Relativo al final actual de la composición.
2.5Segundos locales absolutos.
intro = (
    sequence(
        title.animate.write().duration(0.8),
        label("golpe"),
        subtitle.animate.fade_in().duration(0.4),
    )
    .insert(logo.animate.grow_from_center(), at="golpe+0.15")
    .insert(glow.animate.flash(), at="<")          # empieza con el logo
    .insert(footer.animate.fade_in(), at="-=0.2")  # se solapa con el final
)
print(intro.schedule().labels)  # {'golpe': 0.8}
scene.play(intro)
{'golpe': 0.8}
MÉTODOComposition.defaultsdefaults(*, duration: Optional[float] = None, easing: Optional[Easing] = None) -> Composition
Parámetros
NombreTipoPredeterminadoDescripción
durationfloat | NoneNoneDuración para las animaciones descendientes que no fijan la suya.
easingEasing | NoneNoneEasing para las que no fijan el suyo.
Devuelve: Composition — Una copia configurada.
MÉTODOComposition.delaydelay(seconds: float) -> Composition
Parámetros
NombreTipoPredeterminadoDescripción
secondsfloatobligatorioEspera antes de todo el subárbol.
Devuelve: Composition — Una copia retrasada.
MÉTODOComposition.stretchstretch(seconds: float) -> Composition
Solo para árboles de animaciones: con medios lanza un error, porque cambiaría su velocidad de reproducción.
Parámetros
NombreTipoPredeterminadoDescripción
secondsfloatobligatorioDuración exacta del subárbol.
Devuelve: Composition — Una copia reescalada.
MÉTODOComposition.speed_rampspeed_ramp(speeds: float | Mapping[float, float]) -> Composition
Los speed ramps de los cortes modernos, como ChangeSpeed de Manim o timeScale de GSAP. Antes de la primera clave y después de la última la velocidad se mantiene. La duración pasa a ser la que tarda la rampa; los hijos conservan su orden y sus solapes, y el movimiento de cada clip sigue la rampa dentro de él, así que un seek coincide con la reproducción. Se anida y se combina con stretch, que se aplica después. Los updaters, la física de partículas y el temblor de cámara siguen en tiempo real. Claves fuera de [0, 1] o repetidas, velocidades no positivas o medios lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
speedsfloat | Mapping[float, float]obligatorioVelocidades en fracciones de la composición, de 0 a 1, unidas linealmente: 1 es la velocidad normal, 0.15 una cámara lenta y 2 el doble. Un número es una velocidad constante.
Devuelve: Composition — Una copia con la rampa de velocidad.
Ejemplo
from gaanim import CORAL, GOLD, TEAL, Scene, sequence
scene = Scene(frame=(16, 9))
dots = [scene.geometry.circle(0.3).fill(color).move_to(-6.0, 1.5 - 1.5 * i) for i, color in enumerate((GOLD, CORAL, TEAL))]
steps = [dot.animate.shift_by(10, 0).duration(0.8) for dot in dots]
scene.play(sequence(*steps).speed_ramp({0.0: 1.0, 0.4: 0.15, 0.6: 0.15, 1.0: 1.0}))
scene.render()
animation preview
MÉTODOComposition.time_remaptime_remap(easing: Easing) -> Composition
En la fracción p de su duración, la composición muestra lo que se escribió en easing(p), como el time remap de After Effects o playbackEase de anime.js: Easing.ease_in_out(...) empieza y termina despacio, y Easing.steps(4) avanza a saltos. La duración no cambia. Los easings que retroceden (Back, Elastic, muelles) y los medios lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
easingEasingobligatorioVa de 0 a 1 sin retroceder.
Devuelve: Composition — Una copia con el tiempo remapeado.
MÉTODOComposition.repeatrepeat(count: int, *, delay: float = 0.0) -> Composition
Cada repetición parte del estado en que la dejó la anterior, así que las animaciones relativas se acumulan. Con medios, count < 1 o un delay negativo lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
countintobligatorioRepeticiones; al menos 1.
delayfloat0.0Segundos entre repeticiones.
Devuelve: Composition — El árbol repetido.
Ejemplo
scene.play(parallel(a.animate.rotate_by(math.tau), b.animate.shift_by(1, 0)).repeat(2))
MÉTODOComposition.scheduleschedule(*, duration: Optional[float] = None) -> Schedule
Inspecciona el árbol sin programarlo ni consumir sus hojas y sin mover el cursor.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloat | NoneNoneDuración por defecto exterior con la que se resuelve.
Devuelve: Schedule — Los tiempos locales resueltos.
Ejemplo
plan = sequence(a.animate.fade_in().duration(0.5), b.animate.fade_in().duration(0.5), gap=0.2)
schedule = plan.schedule()
print(schedule.span, [(e.kind, e.start, e.end) for e in schedule.entries])
1.2 [('animation', 0.0, 0.5), ('animation', 0.7, 1.2)]
PROPIEDADSchedule.spanspan: float
Devuelve: float — Duración total de la composición.
PROPIEDADSchedule.entriesentries: tuple[ScheduleEntry, ...]
Cada ScheduleEntry tiene path (índices en el árbol), kind ("animation", "audio", "video" o "lottie"), start, duration y end, en segundos locales; duration y end son None para un medio sin final.
Devuelve: tuple[ScheduleEntry, ...] — Una entrada por hoja.
PROPIEDADSchedule.labelslabels: dict[str, float]
Incluye etiquetas anidadas e insertadas. Una composición reescalada las escala; una repetida informa de la primera repetición.
Devuelve: dict[str, float] — Tiempos de las etiquetas, en segundos locales y en orden temporal.

Los medios también son hojas de composición: VideoSegment admite parallel, sequence y stagger, pero no stretch, y su velocidad se fija al crearlo (ver Medios).

Updaters

Un updater mueve un objeto en cada fotograma sin programar un Anim. Los presets de Updater se evalúan en Rust; se asocian con Drawable.add_updater y se quitan con Drawable.remove_updater. Los objetos generados por updaters siguen ocultos hasta que su propia animación de entrada entra en scene.play.

FÁBRICAUpdater.orbitorbit(cx: float, cy: float, radius: float, speed: float) -> Updater
Coloca el objeto en el círculo según el tiempo transcurrido desde que se asocia.
Parámetros
NombreTipoPredeterminadoDescripción
cx, cyfloatobligatorioCentro de la órbita.
radiusfloatobligatorioRadio.
speedfloatobligatorioVelocidad angular en radianes por segundo.
Devuelve: Updater — Órbita circular.
Ejemplo
planet = scene.geometry.dot(0.12).fill(BLUE)
planet.add_updater(Updater.orbit(0, 0, 2, 1.0))
scene.wait(2)
FÁBRICAUpdater.advance_xadvance_x(speed: float) -> Updater
Parámetros
NombreTipoPredeterminadoDescripción
speedfloatobligatorioUnidades por segundo hacia la derecha; negativo va hacia la izquierda.
Devuelve: Updater — Avance horizontal constante.
FÁBRICAUpdater.bobbob(amplitude: float, frequency: float) -> Updater
Como Updater.pulse y Updater.rotate con un número, es una capa sobre la animación del objeto: función del tiempo desde que se añade, igual en un seek que en la reproducción, que sigue a animate.move_to en lugar de volver a la posición inicial. Las tres se combinan en un mismo objeto. remove_updater() la quita y el objeto vuelve a su posición.
Parámetros
NombreTipoPredeterminadoDescripción
amplitudefloatobligatorioDesplazamiento vertical máximo.
frequencyfloatobligatorioOscilaciones por segundo.
Devuelve: Updater — Oscilación vertical senoidal sumada a la posición del objeto.
FÁBRICAUpdater.rotaterotate(speed: float | Parameter | Computed) -> Updater
Con un número, el ángulo es la velocidad por el tiempo desde que se añade el updater. Con un Parameter, el ángulo es la integral de su valor desde que se añade el updater, así que un seek o una exportación desde la mitad caen en el mismo ángulo que la reproducción, y remove_updater() lo deja en el ángulo alcanzado. Para un Parameter movido por drive_from_samples o add_updater_fn se usa su valor de cada fotograma. Un Computed que depende solo del tiempo (musica.level(), scene.noise) se integra desde el segundo 0 con paso fijo, igual en reproducción y en seek; uno que lee un Parameter lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
speedfloat | Parameter | ComputedobligatorioRadianes por segundo. Con un Parameter, animarlo acelera o frena el giro sin saltos. Con un Computed del tiempo, como una señal de audio, gira a su valor.
Devuelve: Updater — Giro continuo alrededor de Z.
Ejemplo
speed = scene.viz.parameter(0.5)
circle.add_updater(Updater.rotate(speed))
scene.play([speed.animate.set(6.0).duration(2)])  # el clímax: gira cada vez más rápido
scene.play([speed.animate.set(0.5).duration(1)])
FÁBRICAUpdater.pulsepulse(min_scale: float, max_scale: float, frequency: float) -> Updater
Una capa sobre la animación del objeto, como Updater.bob: se combina con Updater.rotate en el mismo objeto.
Parámetros
NombreTipoPredeterminadoDescripción
min_scale, max_scalefloatobligatorioFactores de escala mínimo y máximo respecto de la escala del objeto.
frequencyfloatobligatorioPulsos por segundo.
Devuelve: Updater — Escala que late entre dos factores.
Ejemplo
boat.add_updater(Updater.advance_x(1.5))
fan.add_updater(Updater.rotate(3.0))
heart.add_updater(Updater.pulse(0.9, 1.1, 1.2))
scene.wait(2)
FÁBRICAUpdater.wigglewiggle(*, position: float | Parameter | Computed = 0.08, rotation: float | Parameter | Computed = 0.0, scale: float | Parameter | Computed = 0.0, frequency: float | Parameter | Computed = 2.0, octaves: int = 2, seed: int = 0) -> Updater
Es una capa sobre la animación del objeto: empieza en cero, es función pura del tiempo de la línea de tiempo y se suma a animate.move_to y a otros clips en lugar de sustituirlos. Un seek cae en el mismo fotograma que la reproducción. Las amplitudes y la frecuencia aceptan un Parameter: animar la amplitud a 0 apaga el temblor poco a poco en lugar de cortarlo con remove_updater(), y cambiar la frecuencia cambia el ritmo sin saltos. También aceptan un Computed del tiempo, como musica.pulse(), para temblar con el sonido. Valores inválidos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
positionfloat | Parameter | Computed0.08Amplitud del ruido de posición, en unidades de escena.
rotationfloat | Parameter | Computed0.0Amplitud de giro, en radianes.
scalefloat | Parameter | Computed0.0Amplitud de escala, como fracción.
frequencyfloat | Parameter | Computed2.0Rapidez del temblor.
octavesint2Capas de detalle, de 1 a 8.
seedint0Semilla del ruido.
Devuelve: Updater — Temblor orgánico con semilla.
Ejemplo
logo.add_updater(Updater.wiggle(position=0.08, rotation=0.03, seed=1))
scene.play([logo.animate.move_to(3, 0).duration(2)])  # sigue temblando mientras se mueve

Para atenuarlo, pasa la amplitud como Parameter:

shake = scene.viz.parameter(0.15)
logo.add_updater(Updater.wiggle(position=shake, frequency=3.0, seed=2))
scene.wait(1)
scene.play([shake.animate.set(0).duration(1.5)])  # el temblor se calma
FÁBRICAUpdater.oscillateoscillate(channel: Literal["x", "y", "rotation", "scale", "opacity"], *, waveform: Literal["sine", "square", "triangle", "saw"] = "sine", frequency: float = 1.0, low: float = 0.0, high: float = 1.0, phase: float = 0.0) -> Updater
En x, y y rotation el valor se suma al animado; en scale y opacity lo multiplica (los factores de opacidad deben estar en [0, 1]). Como wiggle, es función pura del tiempo y se combina con animaciones.
Parámetros
NombreTipoPredeterminadoDescripción
channel"x" | "y" | "rotation" | "scale" | "opacity"obligatorioCanal que oscila.
waveform"sine" | "square" | "triangle" | "saw""sine"Forma de la onda.
frequencyfloat1.0Ciclos por segundo.
low, highfloat0.0, 1.0Valores entre los que oscila; toda onda empieza en low.
phasefloat0.0Desfase en ciclos.
Devuelve: Updater — Una capa periódica.
Ejemplo
light = scene.geometry.circle(0.3).fill(GOLD)
light.add_updater(Updater.oscillate("opacity", waveform="triangle", frequency=0.5, low=0.4, high=1.0))
scene.wait(2)
FÁBRICAUpdater.dash_flowdash_flow(speed: float = 0.5) -> Updater
Hace fluir los guiones de todos los trazos del objeto a lo largo de su camino, como hormigas en marcha o el flujo de una tubería. Se suma al dash_offset autorado y es función pura del tiempo, así que los seeks y la exportación coinciden con la reproducción. remove_updater() lo detiene donde está. El trazo necesita guiones (StrokeStyle(dashes=...)). Una velocidad no finita lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
speedfloat0.5Unidades de escena por segundo en el sentido del camino; un valor negativo lo invierte.
Devuelve: Updater — Un flujo de guiones.
Ejemplo
from gaanim import CYAN, Scene, StrokeStyle, Updater
scene = Scene(frame=(16, 9), background="#0f172a")
pipe = scene.geometry.polyline([(-5, -1), (-2, 1.5), (2, -1.5), (5, 1)])
pipe.no_fill().stroke_style(StrokeStyle(CYAN, 0.08, cap="round", dashes=[0.2, 0.18]))
pipe.add_updater(Updater.dash_flow(speed=0.8))
scene.wait(2)
scene.render()
animation preview
MÉTODODrawable.add_updater_fnadd_updater_fn(callback, *, reset=None, fixed_dt=None) -> Drawable
Pasa reset y fixed_dt juntos para física o cualquier estado incremental: tras un seek y durante la exportación, Gaanim restaura la posición inicial, llama a reset() y repite los subpasos constantes, así el resultado es determinista. El updater empieza en el cursor donde se declara, no en segmentos anteriores. Sin esa pareja, la función está pensada para comportamientos ligeros por fotograma o de tiempo absoluto. Coordenadas inválidas o una excepción detienen el updater.
Parámetros
NombreTipoPredeterminadoDescripción
callbackCallableobligatoriocallback((x, y, z), dt, elapsed) devuelve la nueva posición local.
resetCallable | NoneNoneRestaura todo el estado de Python que guarda una simulación.
fixed_dtfloat | NoneNonePaso de simulación positivo, en segundos.
Devuelve: Drawable — El mismo objeto.
Ejemplo
from gaanim import BLACK, GOLD, Scene

scene = Scene(frame=(16, 9), background=BLACK)
ball = scene.geometry.dot(0.15).fill(GOLD).move_to(0, 1.125)
state = {"velocity": 0.0}

def reset():
    state["velocity"] = 0.0

def step(pos, dt, elapsed):
    x, y, z = pos
    state["velocity"] -= 3.0 * dt
    y += state["velocity"] * dt
    if y < -1.125:
        y = -1.125
        state["velocity"] *= -0.8
    return (x, y, z)

ball.add_updater_fn(step, reset=reset, fixed_dt=1 / 240)
scene.wait(3.0)
scene.render()
animation preview
MÉTODODrawable.drive_from_samplesdrive_from_samples(times, values, property="x", *, interpolation="linear", scale=1.0, offset=0.0, colors=None, domain=None) -> Drawable
Mueve el canal como función pura del tiempo, evaluada en Rust, sin llamar a Python en cada fotograma. Los ejes de traslación y rotation son relativos a la pose declarada (base + offset + scale * muestra); scale, opacity y signal son absolutos. Fuera de la serie se mantiene la primera o la última muestra. Los tiempos cuentan desde el cursor donde se llama: una serie declarada después de scene.wait(2.0) reproduce su muestra t = 0 a los dos segundos. Cada canal es independiente; volver a mover el mismo canal lo reemplaza. remove_updater() lo quita. Parameter.drive_from_samples(times, values, *, ...) hace lo mismo con la señal de un parámetro.
Parámetros
NombreTipoPredeterminadoDescripción
times, valuesSequence[float] | Sequence[tuple[float, float]]obligatorioSeries de igual longitud; los tiempos deben ser finitos y no decrecientes. Con "xy", los valores son parejas (x, y).
property"x" | "y" | "xy" | "z" | "rotation" | "scale" | "opacity" | "signal" | "fill""x"Canal que se mueve. "xy" mueve los dos ejes de traslación como canales "x" e "y". "fill" colorea el relleno del objeto y de los miembros de un grupo que lo tengan.
interpolation"linear" | "step""linear"Interpolación entre muestras.
scale, offsetfloat1.0, 0.0Transformación aplicada a cada muestra.
colorsSequence[ColorLike] | NoneNoneSolo con "fill", y obligatorio: al menos dos colores, repartidos por igual sobre domain.
domaintuple[float, float] | NoneNoneSolo con "fill": valores que corresponden al primer y al último color, tras scale y offset. Por defecto, el rango de la serie. Fuera de él se usa el color del extremo.
Devuelve: Drawable — El mismo objeto.
Ejemplo
from gaanim import CYAN, Scene

scene = Scene(frame=(16, 9), background="#0f172a")
times = [i * 0.02 for i in range(len(accel))]
building = scene.geometry.rounded_rect(2, 4.5, 0.125).fill(CYAN).move_to(-2.5, -1.5)
# El edificio oscila con el registro medido; el seek es determinista.
building.drive_from_samples(times, accel, "x", scale=6.5)
scene.play([building.animate.grow_from_center()])
scene.wait(4.0)

Para un ejemplo con varilla, cota y estela, consulta examples/mechanics/simulations.py en el repositorio de Gaanim.

Partículas

scene.fx.particles crea un emisor de partículas determinista: chispas, polvo, humo, nieve o estallidos. Cada partícula tiene forma cerrada: la partícula i del flujo continuo nace en inicio + i / rate, las de una ráfaga nacen juntas en su instante, y su vida, velocidad, dirección, tamaño, color y giro salen de un generador con semilla indexado por (seed, i). Con gravedad y arrastre lineal k, la posición es p0 + v0·(1 − e^(−k·t))/k más el término exacto de la gravedad. Así un seek muestra exactamente lo mismo que la reproducción, la exportación coincide con la vista previa y cada fotograma solo evalúa las partículas vivas en ese instante.

El emisor es un Drawable: su opacidad, sus fundidos y sus transformaciones se aplican a todas sus partículas. Las partículas se dibujan en coordenadas de escena, así que mover el emisor se hace con Emitter.at(...), no con move_to.

MÉTODOFx.particlesscene.fx.particles(emitter=None, *, rate=30.0, duration=None, lifetime=(0.6, 1.2), speed=(1.0, 2.0), direction=pi/2, spread=tau, gravity=(0, 0), drag=0.0, size=(0.03, 0.06), size_end=1.0, fade=0.3, spin=0.0, flutter=0.0, shape="circle", color=WHITE, seed=0) -> Drawable
Los rangos aceptan un número o un par (low, high) y cada partícula elige dentro de ellos. Las ráfagas se añaden con Drawable.burst y animate.burst. Valores no finitos o fuera de rango, más de 16 colores, rate * lifetime por encima de 100 000, una forma desconocida o un objeto de otra escena lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
emitterEmitter | (x, y) | Drawable | None(0, 0)De dónde salen las partículas. Un punto o un objeto equivalen a Emitter.point().at(...).
ratefloat30.0Partículas por segundo desde el cursor de la declaración; 0 solo emite ráfagas.
durationfloat | NoneNoneSegundos de emisión continua; None no se detiene.
lifetimefloat | (low, high)(0.6, 1.2)Vida de cada partícula en segundos; positiva.
speedfloat | (low, high)(1.0, 2.0)Velocidad inicial en unidades por segundo.
directionfloatpi/2Dirección media en radianes (hacia arriba).
spreadfloattauÁngulo completo del cono de direcciones.
gravity(x, y)(0, 0)Aceleración constante, en unidades por segundo al cuadrado.
dragfloat0.0Arrastre lineal por segundo; frena cada partícula hacia su velocidad terminal.
sizefloat | (low, high)(0.03, 0.06)Diámetro o lado, en unidades de escena.
size_endfloat1.0Factor de tamaño al final de cada vida; 0 encoge hasta desaparecer.
fadefloat0.3Fracción final de cada vida en la que la partícula se desvanece, entre 0 y 1.
spinfloat | (low, high)0.0Velocidad de giro en radianes por segundo; un número gira en ambos sentidos hasta ese valor.
flutterfloat0.0Amplitud del vaivén lateral, en unidades.
shapestr"circle""circle", "square", "rect" (tira 2:1), "triangle" o "streak" (chispa estirada según su velocidad).
colorColorLike | Sequence[ColorLike] | BrushWHITEUn color, una lista de la que cada partícula elige uno, o un degradado Brush a lo largo del cual cada partícula toma un color.
seedint0La misma semilla da las mismas partículas.
Devuelve: Drawable — El emisor.
Ejemplo
import math
from gaanim import GOLD, ORANGE, RED, Brush, Emitter, Scene

scene = Scene(frame=(16, 9), background="#0b1020")
logo = scene.geometry.star(5, 0.6, 0.25).fill(GOLD)
sparks = scene.fx.particles(
    emitter=Emitter.circle(radius=0.2).at(logo),
    rate=60, lifetime=(0.6, 1.2), speed=(2.0, 4.0), spread=math.tau,
    gravity=(0, -3), drag=0.8, size=(0.03, 0.08), shape="streak",
    color=Brush.linear([GOLD, ORANGE, RED], start=(0, 0), end=(1, 0)), seed=9,
)
scene.play([logo.animate.move_to(3, 0).duration(1.5)])
scene.play([sparks.animate.burst(80)])
scene.render()
animation preview
MÉTODOFx.confettiscene.fx.confetti(origin=None, count=120, *, seed=0, colors=None, speed=(6, 10), direction=pi/2, spread=0.9, gravity=(0, -6), lifetime=(2.6, 3.6), size=(0.12, 0.2)) -> Drawable
Un preset de Fx.particles: lanza count tiras de papel desde origin en el cursor, hacia direction dentro de un cono de spread radianes. Giran, se balancean y caen con gravity y arrastre, en una paleta festiva salvo que pases colors. Con count=0 no lanza nada hasta burst o animate.burst, que lanzan más del mismo confeti. La misma seed lanza el mismo confeti. Un count por encima de 100 000 o valores no válidos lanzan ValueError.
Ejemplo
from gaanim import Scene

scene = Scene(frame=(16, 9), background="#101828")
confetti = scene.fx.confetti(origin=(0, -4), count=120, seed=2)
scene.wait(3)
scene.render()
animation preview
CLASEEmitterEmitter.point() · circle(radius, *, edge=False) · rect(width, height) · line(length, angle=0.0) · at(target, *, offset=(0, 0))
De dónde salen las partículas de Fx.particles. point: todas del mismo punto. circle: puntos uniformes dentro de un disco, o sobre su borde con edge. rect: puntos uniformes dentro de un rectángulo. line: puntos uniformes sobre un segmento girado angle radianes. at devuelve el mismo emisor centrado en un punto (x, y) o siguiendo un objeto, desplazado offset: cada partícula sale de donde estaba el objeto al nacer ella, así que un objeto que se mueve deja una estela. Dimensiones negativas o no finitas lanzan ValueError; un destino que no sea un punto ni un objeto lanza TypeError.
Ejemplo
snow = scene.fx.particles(Emitter.rect(16, 0.1).at((0, 4.6)), direction=-1.57, spread=0.3, speed=(0.5, 1.0), lifetime=(8, 10), rate=20, fade=0.1)
print(Emitter.circle(0.2, edge=True).at((1, 2)))
Emitter(Circle { radius: 0.2, edge: true } at (1, 2))
MÉTODODrawable.burstburst(count) -> Drawable
Emite count partículas a la vez desde un emisor de scene.fx en el cursor, sin moverlo; antes del primer scene.play la ráfaga ocurre en el instante de la declaración. Un count menor que 1 o mayor que 100 000, o un objeto que no sea un emisor, lanzan ValueError.
Ejemplo
dust = scene.fx.particles((0, -2), rate=0, speed=(0.5, 1.5), lifetime=(1, 2))
dust.burst(40)
scene.wait(2)
MÉTODOAnim.burstanimate.burst(count) -> Anim
Emite count partículas a la vez cuando empieza la animación. Si no fijas duration, la animación dura la vida más larga de las partículas, así que el cursor espera a que se apaguen. No se combina con destinos de propiedad ni con otro efecto en el mismo Anim. Los mismos errores que Drawable.burst.
Ejemplo
sparks = scene.fx.particles((0, 0), rate=0, speed=(2, 4), color=[GOLD, RED], seed=9)
scene.play([sparks.animate.burst(80)])

Falloffs: influencia por instancia

Un Falloff es un valor por instancia calculado a partir de su posición en el grupo, su distancia a un objetivo o un ruido con semilla. Drawable.drive lo conecta a un canal de todos los miembros de un grupo, así que un solo movimiento del cursor escala, tiñe o gira cientos de elementos. Se evalúa en Rust por miembro y fotograma, sin llamar a Python, y es función pura del tiempo de la línea de tiempo: un seek cae en el mismo fotograma que la reproducción. Los valores autorados no se tocan: el efecto se suma o multiplica por encima, como Updater.wiggle.

Los falloffs se combinan con +, - y * (con números u otros falloffs), maximum y minimum, como los modos de combinación de Cavalry.

FÁBRICAFalloff.distancedistance(target: Drawable | tuple[float, float], *, radius: float = 2.0, falloff: Literal["linear", "smooth", "sharp", "round"] = "smooth") -> Falloff
Un radius no positivo o no finito, o una forma desconocida, lanza ValueError; un objetivo de otro tipo lanza TypeError.
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawable | tuple[float, float]obligatorioObjetivo: un objeto, que se sigue allí donde lo lleven sus animaciones, o un punto (x, y).
radiusfloat2.0Distancia, en unidades de escena, a la que la influencia llega a 0.
falloff"linear" | "smooth" | "sharp" | "round""smooth"Forma de la caída: lineal, suave (smoothstep), concentrada junto al objetivo o que llega lejos.
Devuelve: Falloff — 1 en el objetivo y 0 a radius y más allá.
Ejemplo
near = Falloff.distance(cursor, radius=2.0, falloff="smooth")
FÁBRICAFalloff.indexindex(*, easing: Optional[Easing] = None, reverse: bool = False) -> Falloff
Un grupo de un solo miembro da 0.
Parámetros
NombreTipoPredeterminadoDescripción
easingEasing | NoneNoneCurva que da forma a la rampa.
reverseboolFalseCuenta desde el último miembro.
Devuelve: Falloff — 0 para el primer miembro y 1 para el último.
Ejemplo
fade_in_order = Falloff.index(easing=Easing.SMOOTH).remap(0.2, 1.0)
FÁBRICAFalloff.linearlinear(start: Drawable | tuple[float, float], end: Drawable | tuple[float, float], *, falloff: Literal["linear", "smooth", "sharp", "round"] = "linear") -> Falloff
Los miembros antes de start reciben 0 y los que pasan de end reciben 1: al mover un extremo, una ola cruza el grupo.
Parámetros
NombreTipoPredeterminadoDescripción
start, endDrawable | tuple[float, float]obligatorioExtremos de la línea, objetos o puntos.
falloffstr"linear"Forma de la rampa, como en Falloff.distance.
Devuelve: Falloff — 0 en start, 1 en end y proporcional entre ambos.
Ejemplo
wave = Falloff.linear((-6, 0), (6, 0), falloff="smooth")
FÁBRICAFalloff.noisenoise(*, frequency: float = 0.5, scale: float = 0.5, octaves: int = 1, seed: int = 0) -> Falloff
Valores fuera de rango lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
frequencyfloat0.5Rapidez con que el campo se desplaza en el tiempo.
scalefloat0.5Ciclos de ruido por unidad de escena: los vecinos reciben valores parecidos.
octavesint1Capas de detalle, de 1 a 8.
seedint0Semilla: la misma da el mismo campo.
Devuelve: Falloff — Ruido simplex en [0, 1] sobre la posición de cada miembro y el tiempo.
Ejemplo
sway = Falloff.noise(frequency=0.4, seed=2).remap(-0.3, 0.3)
FÁBRICAFalloff.constantconstant(value: float) -> Falloff
Sirve para combinar: near.maximum(Falloff.constant(0.3)). Un valor no finito lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
valuefloatobligatorioValor finito.
Devuelve: Falloff — El mismo valor para todos los miembros.
Ejemplo
half = Falloff.constant(0.5)
FÁBRICAFalloff.sourcesource(value: Computed) -> Falloff
Lleva al drive una señal del tiempo, por ejemplo para que el color siga al audio. Un Computed que lee un Parameter lanza ValueError. Ver Audio.
Parámetros
NombreTipoPredeterminadoDescripción
valueComputedobligatorioUn Computed que depende solo del tiempo: una señal de audio, scene.noise o scene.time.
Devuelve: Falloff — Su valor, el mismo para todos los miembros.
Ejemplo
bajo = scene.media.audio("assets/ritmo.ogg").band(20, 150, smoothing=0.5)
dots.drive("fill", Falloff.source(bajo).gradient(BLUE, GOLD))
MÉTODOFalloff.remapremap(low, high) -> Falloff
near.remap(1.0, 1.8) escala de 1 a 1.8 conforme el miembro se acerca al objetivo. Falloff.invert() devuelve 1 - valor.
Parámetros
NombreTipoPredeterminadoDescripción
low, highfloatobligatorioValores finitos: 0 se convierte en low y 1 en high.
Devuelve: Falloff — Un falloff nuevo.
Ejemplo
grow = near.remap(1.0, 1.8)
far = near.invert()
MÉTODOFalloff.gradientgradient(*colors) -> FalloffColor
Menos de dos colores lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
colorsColorLikeobligatorioAl menos dos colores, repartidos a partes iguales: 0 es el primero y 1 el último.
Devuelve: FalloffColor — El falloff convertido en color, para drive(\"fill\", ...).
Ejemplo
heat = near.gradient(BLUE, GOLD)
MÉTODOFalloff.maximum / minimummaximum(other) -> Falloff · minimum(other) -> Falloff
Un operando de otro tipo lanza TypeError. a + b, a - b y a * b combinan igual.
Parámetros
NombreTipoPredeterminadoDescripción
otherFalloff | floatobligatorioCon quien se combina.
Devuelve: Falloff — El mayor o el menor de los dos valores, miembro a miembro.
Ejemplo
both = a.maximum(b)
sum_of = a + b
MÉTODODrawable.drivedrive(channel, value) -> None
Sobre un grupo (por ejemplo el de scene.geometry.duplicate) actúa sobre cada miembro; sobre un objeto suelto, sobre él mismo. Varios drive sobre un canal se combinan. clear_drive() los termina en el cursor. Un canal desconocido lanza ValueError, un valor del tipo equivocado lanza TypeError y un objetivo de otra escena lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
channel"scale" | "rotation" | "opacity" | "x" | "y" | "fill"obligatorioCanal: scale y opacity multiplican el valor autorado, rotation suma radianes, x e y suman unidades de escena y fill sustituye el color de relleno.
valueFalloff | FalloffColorobligatorioUn Falloff para los canales numéricos; el FalloffColor de Falloff.gradient para fill.
Devuelve: None — Se aplica desde el cursor de la línea de tiempo.
Ejemplo
import math
from gaanim import BLUE, GOLD, WHITE, Distribution, Easing, Falloff, Scene

scene = Scene(frame=(16, 9), background="#0f172a")
tip = scene.geometry.regular_polygon(3, 0.17).fill(BLUE).no_stroke()
grid = scene.geometry.duplicate(tip, Distribution.grid(20, 12, 0.7))
cursor = scene.geometry.dot(0.12).fill(WHITE).move_to(-6.5, 0)

near = Falloff.distance(cursor, radius=2.5, falloff="smooth")
grid.drive("scale", near.remap(1.0, 1.9))
grid.drive("fill", near.gradient(BLUE, GOLD))
grid.drive("opacity", Falloff.index(easing=Easing.SMOOTH).remap(0.35, 1.0))
grid.look_at(cursor, offset=-math.pi / 2)  # la punta mira al cursor

scene.play([cursor.animate.move_to(6.5, 0).duration(2.5).easing(Easing.SMOOTH)])
scene.render()
animation preview
MÉTODODrawable.look_atlook_at(target, *, offset=0.0) -> None
Gira el objeto, o cada miembro de un grupo, para que su eje x apunte al objetivo. Se suma al giro autorado y a los drive("rotation", ...). Un objetivo de otro tipo lanza TypeError y uno de otra escena ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
targetDrawable | tuple[float, float]obligatorioHacia dónde mira: un objeto, que se sigue allí donde vaya, o un punto.
offsetfloat0.0Radianes que se suman, para formas que apuntan hacia otro lado (un triángulo apunta hacia arriba: usa -math.pi / 2).
Devuelve: None — Se aplica desde el cursor de la línea de tiempo.
Ejemplo
needles.look_at(cursor)
scene.render()
MÉTODODrawable.clear_driveclear_drive() -> None
Los drive dejan de sumar su desplazamiento, así que los valores autorados vuelven a verse desde ese instante. Un look_at deja el objeto girado como estaba en el cursor: ese giro, medido sobre las posiciones autoradas, pasa a su rotación (si el objetivo solo lo mueve un updater, puede quedar un poco desviado). Lo anterior no cambia.
Devuelve: None — Termina en el cursor todos los drive y look_at del objeto o de los miembros del grupo.
Ejemplo
scene.wait(1)
dots.clear_drive()
scene.render()

Transformaciones 3D

Los mismos destinos en tres ejes, para objetos en el espacio de una cámara en perspectiva. Las rotaciones de Euler usan orden XYZ y radianes.

MÉTODOAnim.move_to_3dmove_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
x, y, zScalarSourceobligatorioPosición de destino.
Devuelve: Anim — Movimiento a una posición 3D.
MÉTODOAnim.shift_by_3dshift_by_3d(dx: float, dy: float, dz: float) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
dx, dy, dzfloatobligatorioDesplazamiento en unidades de escena.
Devuelve: Anim — Movimiento relativo en 3D.
MÉTODOAnim.rotate_to_3drotate_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
x, y, zScalarSourceobligatorioOrientación de Euler XYZ absoluta, en radianes.
Devuelve: Anim — Giro a una orientación.
MÉTODOAnim.rotate_by_3drotate_by_3d(axis: Literal["x", "y", "z"], radians: float) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
axis"x" | "y" | "z"obligatorioEje de giro; otro valor lanza ValueError.
radiansfloatobligatorioÁngulo relativo.
Devuelve: Anim — Giro relativo alrededor de un eje.
MÉTODOAnim.scale_to_3dscale_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
x, y, zScalarSourceobligatorioEscala absoluta por eje.
Devuelve: Anim — Cambio de escala por eje.
MÉTODOAnim.scale_by_3dscale_by_3d(x: float, y: float, z: float) -> Anim
Parámetros
NombreTipoPredeterminadoDescripción
x, y, zfloatobligatorioFactores que multiplican la escala de cada eje.
Devuelve: Anim — Cambio de escala relativo por eje.
MÉTODOAnim.materialmaterial(material: Material3D) -> Anim
Solo en una Primitive3D. Color, color emisivo, rugosidad, metalicidad e intensidad de emisión se interpolan de forma determinista y los extremos exactos se restauran al buscar. En una malla, write() lanza TypeError: usa create(), que crece desde el centro mientras aparece.
Parámetros
NombreTipoPredeterminadoDescripción
materialMaterial3DobligatorioMaterial de destino.
Devuelve: Anim — Interpolación del material.
Ejemplo
cube = scene.geometry.cube(1.5).material(Material3D.matte(BLUE))
scene.play(cube.animate.material(Material3D.metal(GOLD)).rotate_by_3d("y", 1.2).duration(1.2))

Transiciones entre segmentos

Transition describe el paso de un segmento al siguiente en scene.segment(...) o scene.link(...). Todas salvo cut aceptan easing=, con cualquier Easing, incluidos los resortes que se pasan del destino, y todas aceptan overlay=, un Overlay dibujado encima del corte. Ninguna de las dos opciones cambia la duración de los segmentos. Sin easing, cross_fade, fade_through y zoom_through avanzan de forma lineal, morph y magic_move se mueven con Easing.SMOOTH y funden de forma lineal, y los revelados vectoriales (wipe, clock_wipe, iris, blinds, push y slide) usan Easing.SMOOTH. Con un resorte o una curva de retroceso, el movimiento se pasa del destino y vuelve, pero los fundidos siguen la curva sin retroceder: una vez pasado el destino, el fundido ha terminado.

Todas aceptan también sound=, la ruta de un efecto de sonido (relativa a la carpeta de assets) que suena una vez, con volumen 1, cuando empieza la transición, es decir, al inicio del segmento al que entra. Se mezcla como scene.media.audio en la vista previa y en MP4/WebM y no cambia ninguna duración; consulta Audio.

Los revelados vectoriales recortan ambos segmentos con caminos animados dentro del marco visible de la cámara: el entrante se ve dentro de la región revelada y el saliente en el resto; si los fondos son distintos, el entrante se revela con la misma forma. Son geometría vectorial, sin texturas intermedias, así que la transición es nítida a cualquier resolución y un seek reproduce exactamente el mismo fotograma. Los objetos persistentes (scene.persist) no se recortan ni se desplazan.

FÁBRICATransition.cutcut(*, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Parámetros
NombreTipoPredeterminadoDescripción
overlayOverlay | NoneNoneCapa dibujada sobre el corte.
Devuelve: Transition — Cambio instantáneo.
FÁBRICATransition.cross_fadecross_fade(duration: float, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
El segmento saliente se desvanece mientras aparece el entrante.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
easing, overlayEasing | None, Overlay | NoneNoneComunes a todas las transiciones.
Devuelve: Transition — Fundido cruzado.
Ejemplo
scene.segment("detalle", Transition.cross_fade(0.4))
scene.wait(1)
FÁBRICATransition.fade_throughfade_through(duration: float, color: ColorLike, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Funde a color durante la primera mitad y desde él al segmento entrante en la segunda.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
colorColorobligatorioColor intermedio.
Devuelve: Transition — Fundido a través de un color.
Ejemplo
scene.segment("capítulo 2", Transition.fade_through(1.0, BLACK))
scene.wait(1)
FÁBRICATransition.slideslide(duration: float, direction: str, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
El segmento saliente queda quieto y el entrante lo cubre al recorrer un ancho o un alto de marco. Usa push para mover los dos. Otra dirección lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
directionstrobligatorioMovimiento del marco entrante: "left", "right", "up" o "down".
Devuelve: Transition — El entrante se desliza sobre el saliente.
Ejemplo
scene.segment("detalle", Transition.slide(0.5, "left", sound="whoosh.wav"))
scene.wait(1)
FÁBRICATransition.pushpush(duration: float, direction: str = "up", *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
El segmento entrante empuja al saliente fuera del marco: ambos se desplazan un ancho o un alto de marco y cada uno queda recortado a su propio marco.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
directionstr"up"Movimiento de ambos marcos: "left", "right", "up" o "down".
Devuelve: Transition — Empuje.
Ejemplo
scene.segment("siguiente", Transition.push(0.5, direction="up"))
scene.wait(1)
scene.segment("final", Transition.slide(0.5, "left", easing=Easing.spring(bounce=0.2)))
scene.wait(1)
FÁBRICATransition.shadershader(source: str | os.PathLike[str], duration: float, *, uniforms: Optional[Mapping[str, float | Parameter | Variable | Computed | TimeInput]] = None, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Dibuja cada segmento por separado, con su fondo, y los mezcla en la GPU, como gl-transitions. La función lee gaanim_from(uv) (saliente), gaanim_to(uv) (entrante), progress (de 0 a 1, lineal salvo easing=), gaanim_resolution() y gaanim_time(); uv vale (0, 0) arriba a la izquierda del cuadro. Los objetos persistentes y el overlay quedan nítidos encima. WGSL o nombres de uniform inválidos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
sourcestr | os.PathLikeobligatorioWGSL en línea o un archivo .wgsl (una ruta relativa se busca en el directorio de trabajo, luego en la carpeta assets del script y luego junto a él) que define fn transition(uv: vec2<f32>) -> vec4<f32>.
durationfloatobligatorioSegundos, positivo.
uniformsMapping[str, float | Parameter | Computed] | NoneNoneCampos de gaanim_uniforms: los números son fijos; un Parameter, Variable, Computed, scene.time o una señal de audio de la misma escena se evalúa en cada fotograma de la transición, así que puede latir con el bombo. Los paquetes .gaanim guardan los valores.
Devuelve: Transition — Transición por shader.
Ejemplo
mezcla = Transition.shader(
    "fn transition(uv: vec2<f32>) -> vec4<f32> { return mix(gaanim_from(uv), gaanim_to(uv), progress); }",
    0.6,
)
scene.segment("despues", mezcla)
scene.wait(1)
FÁBRICATransition.presetpreset(name: Literal["cross_zoom", "directional_warp", "ripple", "glitch_displace", "luma"], duration: float, *, image: Optional[str | os.PathLike[str]] = None, invert: bool = False, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None, **settings: float | int) -> Transition
Un nombre o un ajuste desconocidos, image en otro preset o luma sin imagen lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
namestrobligatorio"cross_zoom", "directional_warp", "ripple", "glitch_displace" o "luma".
durationfloatobligatorioSegundos, positivo.
image / invertstr | os.PathLike | None / boolNone / FalseSolo luma: mapa en escala de grises (reducido a 256 px como mucho; una ruta relativa se busca como en source); el segmento entrante aparece primero donde es más oscuro, o más claro con invert=True.
**settingsfloat | intobligatoriobands y seed son enteros; los demás, números reales. cross_zoom: strength=0.4. directional_warp: dx=1, dy=0 (y hacia arriba), smoothness=0.5. ripple: amplitude=100, speed=50. glitch_displace: strength=0.5, bands=24, seed=0. luma: softness=0.1.
Devuelve: Transition — Transición por shader incorporada.
Ejemplo
scene.segment("despues", Transition.preset("directional_warp", 0.8, dx=0, dy=1))
scene.wait(1)
FÁBRICATransition.zoom_throughzoom_through(duration: float, *, center: tuple[float, float] = (0.0, 0.0), max_zoom: float = 4.0, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Acerca la cámara a un punto del segmento saliente y la aleja en el entrante; útil cuando un detalle presenta la sección siguiente.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
centertuple[float, float](0.0, 0.0)Punto de la escena hacia el que se acerca.
max_zoomfloat4.0Zoom máximo, en el corte.
Devuelve: Transition — Zoom a través del corte.
Ejemplo
scene.segment("detalle", Transition.zoom_through(1.0, center=(2, 1), max_zoom=4))
scene.wait(1)
FÁBRICATransition.morphmorph(duration: float, *, pairs: Sequence[tuple[Drawable, Drawable]] = (), easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Cada pareja comparte una caja que viaja de la caja del origen a la del destino, mientras el destino aparece en la primera mitad y el origen desaparece en la segunda: se lee como un solo objeto que cambia de lugar, tamaño, color y forma. El resto del contenido hace un fundido cruzado. Las parejas se resuelven al compilar, así que se pasan a scene.link cuando existen los dos segmentos. Una duración no positiva, un objeto emparejado consigo mismo o repetido en un lado lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
pairsSequence[tuple[Drawable, Drawable]]()Parejas (origen, destino): el origen en el segmento saliente y el destino en el entrante.
Devuelve: Transition — Continuidad de objetos a través del corte.
Ejemplo
overview = scene.segment("Resumen")
card = scene.geometry.rect(3, 2).fill(BLUE).move_to(-4, 0)
scene.wait(1)
detail = scene.segment("Detalle")
panel = scene.geometry.rect(12, 6).fill(BLUE)
scene.wait(1)
scene.link(overview, detail, Transition.morph(0.8, pairs=[(card, panel)]))
FÁBRICATransition.magic_movemagic_move(duration: float, *, key: Literal["name", "id"] = "name", easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Como Transition.morph, pero las parejas se buscan al compilar entre los objetos de los dos segmentos que comparten clave: los de primer nivel y los miembros de sus grupos, donde un grupo con clave se mueve entero. Las claves repetidas se emparejan en orden de declaración y se ignoran los objetos ocultos al final del segmento saliente, como el origen de un magic_move terminado. El resto hace un fundido cruzado. Para claves calculadas con una función, usa magic_move. Una duración no positiva o una clave desconocida lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
keystr"name""name" empareja los nombres de Drawable.named (o el id de una parte SVG sin nombre); "id", solo los id SVG.
easing, overlayEasing | None, Overlay | NoneNoneComunes a todas las transiciones.
Devuelve: Transition — Transition.morph con parejas por clave.
Ejemplo
scene.segment("v1")
scene.geometry.rect(3, 2).fill(BLUE).move_to(-4, 0).named("card")
scene.wait(1)
scene.segment("v2", transition=Transition.magic_move(0.8, key="name"))
scene.geometry.rect(8, 5).fill(GOLD).named("card")
scene.wait(1)
FÁBRICATransition.wipewipe(duration: float, direction: str = "left", feather: float = 0.1, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Un borde recto cruza el marco y descubre el segmento entrante. El borde suave es una rampa de alfa vectorial. Una duración no positiva, una dirección desconocida o un feather fuera de [0, 1] lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
directionstr"left"Sentido en que viaja el borde: left, right, up, down o una diagonal como up_left. Con "left" el revelado empieza en el lado derecho.
featherfloat0.1Ancho del borde suave como fracción del recorrido, en [0, 1]; 0 da un borde duro.
Devuelve: Transition — Barrido lineal.
Ejemplo
scene.segment("detalle", Transition.wipe(0.6, direction="left", feather=0.1))
FÁBRICATransition.clock_wipeclock_wipe(duration: float, start_angle: float = 90.0, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Una aguja gira en sentido horario alrededor del centro del marco y deja ver el segmento entrante en el sector recorrido.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
start_anglefloat90.0Grados en sentido antihorario desde +x; 90 empieza a las doce.
Devuelve: Transition — Barrido radial.
Ejemplo
scene.segment("resumen", Transition.clock_wipe(0.8, start_angle=90))
FÁBRICATransition.irisiris(duration: float, center: tuple[float, float] = (0.0, 0.0), shape: str | Drawable = "circle", *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
La forma crece desde center hasta que el segmento entrante ocupa todo el marco. Un Drawable se centra en su caja; se sigue dibujando en su propio segmento, así que conviene ocultarlo si solo sirve de plantilla. Uno sin camino vuelve al círculo. Un nombre desconocido lanza ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
centertuple[float, float](0.0, 0.0)Centro del iris en unidades de escena.
shapestr | Drawable"circle"circle, diamond, square, star o un Drawable cuyo contorno vectorial se usa como plantilla.
Devuelve: Transition — Iris que crece hasta cubrir el marco.
Ejemplo
scene.segment("zoom", Transition.iris(0.7, center=(2, 1), shape="star"))
FÁBRICATransition.blindsblinds(duration: float, count: int = 8, angle: float = 0.0, *, easing: Optional[Easing] = None, overlay: Optional[Overlay] = None, sound: Optional[str] = None) -> Transition
Todas las lamas se abren a la vez y en la misma fracción.
Parámetros
NombreTipoPredeterminadoDescripción
durationfloatobligatorioSegundos, positivo.
countint8Número de lamas, entre 1 y 512.
anglefloat0.0Inclinación de las lamas en grados; 0 son lamas horizontales que se abren hacia abajo.
Devuelve: Transition — Persiana veneciana.
Ejemplo
scene.segment("datos", Transition.blinds(0.6, count=8, angle=0))
FÁBRICAOverlay.flashflash(color: Optional[ColorLike] = None, duration: float = 0.2) -> Overlay
Cubre el marco con un color que sube durante la primera mitad y se apaga en la segunda, centrado en el punto medio de la transición (en cut, en el propio corte).
Parámetros
NombreTipoPredeterminadoDescripción
colorColor | NoneNoneColor del destello; blanco si se omite.
durationfloat0.2Segundos, positivo.
Devuelve: Overlay — Capa para overlay= de cualquier Transition.
Ejemplo
scene.segment("impacto", Transition.cut(overlay=Overlay.flash(WHITE, 0.15)))
FÁBRICAOverlay.light_leaklight_leak(seed: int = 0, hue: float = 0.1, duration: float = 0.8, intensity: float = 0.8) -> Overlay
Manchas de luz suaves en modo pantalla (screen) que derivan por el marco alrededor del corte. Es función pura del tiempo y de la semilla, así que la previsualización, los seeks y la exportación coinciden. Valores fuera de rango lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
seedint0Semilla de la disposición de las manchas de luz.
huefloat0.1Tono base en vueltas: 0.1 naranja cálido, 0.6 azul.
durationfloat0.8Segundos, positivo.
intensityfloat0.8Brillo máximo, en [0, 4].
Devuelve: Overlay — Capa para overlay=.
Ejemplo
scene.segment("cálido", Transition.cross_fade(0.4, overlay=Overlay.light_leak(seed=2, hue=0.1)))