El handle fluido que devuelven todas las fábricas: estilo, posición, efectos, anclajes y relaciones reactivas
Cada fábrica de la escena (scene.geometry, scene.text, scene.media, scene.viz, scene.slides, scene.mechanics, scene.layout) devuelve un Drawable: un handle que encadena estilo, posición y efectos. Los tipos especializados (Text, Image, Layout, Dimension…) heredan todos estos métodos y conservan su tipo al encadenarlos.
from gaanim import BLUE, GOLD, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
card = scene.geometry.rounded_rect(3, 1.6, 0.2).fill(BLUE).stroke(GOLD, 0.04)
card.move_to(-2, 0).rotate_to(0.1).shadow("#00000099")
scene.play([card.animate.move_to(2, 0).rotate_to(-0.1).duration(1.2)])
scene.render()
Hay dos formas de cambiar un objeto:
Los setters inmediatos (fill, move_to, opacity…) fijan el estado inicial. Si los llamas después de un play o un wait, crean un corte reversible en el cursor de la línea de tiempo.
El proxy .animate usa el mismo vocabulario, pero devuelve un Anim que interpola hacia el destino dentro de scene.play(...). Consulta Animaciones para las entradas, los énfasis y el control del tiempo.
Estilo
Relleno, trazo, opacidad y orden de dibujo. Los colores aceptan Color, cadenas CSS o hex y Brush para degradados (ver Colores y temas).
MÉTODODrawable.fillfill(paint: Paint) -> Self
Pinta el interior de los contornos cerrados. En un grupo o un SVG importado, el color llega a todos los descendientes.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
paint
Paint
obligatorio
Color, cadena CSS/hex, tupla RGB(A) o Brush.
Ejemplo
disk = scene.geometry.circle(1).fill(BLUE)
badge = scene.geometry.square(1).fill("#f97316").move_to(3, 0)
MÉTODODrawable.no_fillno_fill() -> Self
Quita el relleno. Úsalo para contornos: circle(1).no_fill().stroke(WHITE, 0.04).
En contornos cerrados, incluidos los glifos de un texto, el trazo queda entero dentro por defecto, así write dibuja un ancho constante. "center" lo reparte a ambos lados y "outside" lo dibuja entero por fuera, por ejemplo como halo bajo una etiqueta que tapa líneas. Los caminos abiertos siempre centran su trazo. La alineación es estado de declaración y no se anima; otros valores lanzan ValueError. Los guiones conservan su longitud con cualquier alineación, y los remates, uniones y guiones fijados antes con stroke_style se conservan: stroke solo cambia la pintura y el ancho.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
paint
Paint
obligatorio
Color o Brush.
width
float
obligatorio
Ancho en unidades lógicas de escena. No sigue la escala de la figura: scale_to, scale_to_3d, matrix_to, las inclinaciones, la escala de sus grupos y sus animaciones cambian la forma, no el pincel, que queda redondo e igual de ancho en todos los lados. También en SVG escalados.
align
str | None
None
"inside", "center" u "outside" respecto a los contornos cerrados; None deja el trazo dentro. En los tres casos el trazo visible mide width.
scale_with_object
bool | None
None
True hace que el ancho siga la escala de la figura, como scale_stroke_with_object.
Ejemplo
from gaanim import Anchor, BLACK, RED, WHITE, Scene
scene =Scene(frame=(16, 9), background=WHITE)
scene.geometry.line(-6, -0.4, 6, 0.4).stroke(RED, 0.04)
scene.text("halo", size=0.8).fill(WHITE).stroke(WHITE, 0.15, align="outside").move_to(0, 0, Anchor.CENTER)
scene.text("halo", size=0.8).fill(BLACK).move_to(0, 0, Anchor.CENTER)
scene.wait(0.1)
scene.render()
Hace que el ancho del trazo siga la escala que acumula la figura (la suya, la de sus grupos y la de un espacio de coordenadas), como un dibujo que se amplía: al escalar una cara ×1.18, las cejas y la nariz engrosan con ella. Una escala no uniforme ensancha el pincel en su eje. En un grupo o un SVG importado se aplica a todos sus trazos. Es estado de declaración y no se anima.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
enabled
bool
True
False vuelve al ancho en unidades de escena.
Ejemplo
face = scene.geometry.group([head, brow]).scale_stroke_with_object()
face.scale_to(1.18)
MÉTODODrawable.chalkchalk(seed: int = 0, roughness: float = 0.01) -> Self
Dibuja el relleno y el trazo como tiza en una pizarra: el contorno tiembla un poco y un grano rompe la pintura. En un texto o un grupo se aplica a cada glifo y miembro. Vale para toda la escena, aunque se llame después de un play; no se anima. write(brush="chalk") hace lo mismo desde la animación. Los paquetes .gaanim la graban y reproducen igual.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
seed
int
0
Semilla del temblor y del grano: la misma semilla dibuja la misma tiza en cada fotograma y exportación.
roughness
float
0.01
Desplazamiento máximo del contorno, en unidades de escena; 0 deja el contorno limpio y solo aplica el grano.
Aplica la geometría completa del trazo; el align del estilo, si lo tiene, coloca el trazo como stroke(align=...). En una llamada directa, la pintura debe ser un color CSS literal o un Brush; los nombres de token se resuelven cuando el StrokeStyle va dentro de Theme.styles. Métricas inválidas lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
style
StrokeStyle
obligatorio
Pintura, ancho, extremo, unión, límite de inglete, guiones, desfase de guiones y alineación.
Añade una clase ordenada que usa Theme.styles. Varias llamadas se aplican en cascada, en orden; los estilos del constructor y los setters fluidos siguen teniendo prioridad. En un grupo, la clase llega a todos los miembros visuales.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
name
str
obligatorio
Clase del tema sin el punto inicial; admite letras, dígitos, _ y -.
Ejemplo
from gaanim import Scene, Style, Theme
theme =Theme("paper", styles={".warning": Style(fill="#e11d48")})
scene =Scene(frame=(16, 9), theme=theme)
warning = scene.geometry.square(1.125).style_class("warning")
scene.wait(0.1)
scene.render()
La opacidad se multiplica por la jerarquía: la de un grupo escala la de sus miembros sin cambiar sus valores propios. Un grupo o un SVG translúcido se compone como una sola capa, como opacity en CSS: al fundirlo, lo que una pieza tapa sigue tapado (los ojos no asoman bajo los párpados) y las piezas translúcidas no se marcan más. Con una fuente reactiva el canal queda vinculado desde el cursor; un número termina el vínculo con un corte reversible. Mientras esté vinculado, anima la fuente: animar el canal directamente lanza un error.
El z_index de un grupo o de un texto se suma al de cada descendiente, así que mueve todo el subárbol. Los empates conservan el orden de creación. Con capas (Scene.z_layers), ordena solo dentro de la capa del objeto.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
z
int
obligatorio
Capa de dibujo; los valores mayores quedan encima.
Ejemplo
front = scene.geometry.circle(1).fill(GOLD).z_index(5)
back = scene.geometry.rect(3, 1).fill(BLUE)
MÉTODODrawable.z_layerz_layer(name: str) -> Self
Dibuja el objeto en la capa name: queda encima de todo lo que está en las capas de detrás, sea cual sea su z_index, que solo ordena dentro de la capa. Un grupo o un texto se lleva a sus miembros, salvo a los que nombran su propia capa. El orden de dibujo vale para toda la escena, así que una llamada después de mostrar el objeto también rige desde el principio. Un nombre que la escena no declaró lanza ValueError.
Marca que el objeto, y sus miembros si es un grupo, tapa textos a propósito, como un diálogo dibujado sobre un modelo mientras se explica: el aviso de textos tapados de gaanim check deja de contar los textos que tapa. No cambia nada del dibujo y vale para toda la escena.
Da un nombre al objeto y lo devuelve; Drawable.name lo lee (None si no tiene). El nombre identifica al mismo objeto en dos estados: magic_move y Transition.magic_move emparejan los objetos con el mismo nombre. Un nombre en blanco lanza ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
name
str
obligatorio
Nombre no vacío; no hace falta que sea único.
Ejemplo
bar = scene.geometry.rect(3, 0.5).fill(BLUE).named("ana")
print(bar.name)
ana
Posición y transformaciones
Setters absolutos (move_to, scale_to, rotate_to, skew_to) y relativos (shift_by, scale_by, rotate_by) en unidades de escena y radianes. Sus versiones animadas están en Animaciones.
MÉTODODrawable.move_tomove_to(x, y, anchor=None) | move_to(reference) | move_to(point) -> Self
Sin anchor, los objetos se colocan por su centro visual, medido con la geometría tal como se declaró: mover después una parte de un SVG (svg.part("g").shift_by(...)) no mueve el SVG entero; las raíces de sistemas de coordenadas colocan su origen matemático, para que las etiquetas no desplacen los ejes. move_to(reference) crea una relación de layout diferida centro con centro que no sigue animaciones posteriores: usa follow o attach_to para eso. Una referencia o un AnchorPoint no se combinan con y ni con anchor. Text acepta además TextAnchor (ver Texto). Ojo: sin anchor, un texto de una línea se coloca por su línea base (TextAnchor.BASELINE_CENTER), no por su centro visual, así que un título con move_to(0, y) queda medio cuerpo más arriba; usa move_to(0, y, Anchor.CENTER) para centrarlo. Las coordenadas aceptan fuentes reactivas, con las mismas reglas que opacity.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
x / y
float | fuente reactiva
obligatorio
Posición de destino en unidades de escena.
anchor
Anchor | str | None
None
Un Anchor o su nombre, como "top_left". Punto propio que se coloca en (x, y); posicional o por nombre.
reference
Drawable
obligatorio
Alternativa: centra este objeto sobre otro.
point
AnchorPoint
obligatorio
Alternativa: coloca el centro sobre un anclaje de otro objeto.
Fija la rotación absoluta en radianes alrededor del pivote (ver with_pivot); los valores positivos giran en sentido antihorario. Acepta fuentes reactivas.
Fija el sesgo (skew) absoluto alrededor del pivote; (0, 0) lo quita. Los factores son tangentes sin unidades: con el pivote en la base, skew_to(0.15, 0) desplaza la parte superior 0.15 unidades por cada unidad de altura. En un grupo deforma a todos los hijos a la vez, sin trocear la figura. animate.skew_to(x, y) lo anima. Lanza ValueError con factores no finitos.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
x
float
obligatorio
Corte horizontal: cada punto se desplaza en x x veces su altura sobre el pivote.
y
float
obligatorio
Corte vertical: cada punto se desplaza en y y veces su distancia horizontal al pivote.
Ejemplo
from gaanim import BLUE, GOLD, Easing, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
ground = scene.geometry.rect(8, 0.1).fill(GOLD).move_to(0, -2.05)
house = scene.geometry.group([
scene.geometry.rect(3, 2.5).fill(BLUE).move_to(0, -0.75),
scene.geometry.polygon([(-1.8, 0.5), (1.8, 0.5), (0, 2)]).fill(BLUE),
]).with_pivot(0, -2)
scene.play(house.animate.skew_to(0.2, 0).duration(0.4).easing(Easing.SMOOTH))
scene.play(house.animate.skew_to(-0.12, 0).duration(0.4).easing(Easing.SMOOTH))
scene.play(house.animate.skew_to(0, 0).duration(0.5).easing(Easing.SMOOTH))
scene.render()
Aplica una transformación lineal 2D cualquiera alrededor del pivote y sustituye el giro, el sesgo y la escala actuales. A diferencia de skew_to, lleva los ejes x e y a cualquier dirección, así que una cara dibujada de frente pasa a una proyección isométrica u oblicua sin trocearla. animate.matrix_to(...) la anima: se descompone en giro, sesgo y escala, que se interpolan juntos. Lanza ValueError con una matriz no finita o no invertible.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
matrix
tuple[tuple[float, float], tuple[float, float]]
obligatorio
Filas ((a, b), (c, d)) de la aplicación (x, y) → (a x + b y, c x + d y).
Ejemplo
import math
from gaanim import BLUE, GOLD, GRAY, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
c, s = math.cos(math.pi /6), math.sin(math.pi /6)
# Las caras giran sobre su centro: el eje x baja o sube 30°, el y sigue vertical.
side = scene.geometry.rect(3, 2).fill(BLUE).stroke(GRAY, 0.03).move_to(-1.3, 0)
front = scene.geometry.rect(3, 2).fill(GOLD).stroke(GRAY, 0.03).move_to(1.3, 0)
scene.play([
side.animate.matrix_to(((c, 0), (-s, 1))).duration(0.8),
front.animate.matrix_to(((c, 0), (s, 1))).duration(0.8),
])
scene.render()
MÉTODODrawable.boundsbounds() -> Bounds
Mide la caja de cualquier objeto (figuras, texto, matemática, SVG, imágenes, grupos) en el cursor actual, tal como se dibujaría ahí: cuenta la maquetación, las transformaciones, la composición del texto, las animaciones que terminaron hasta scene.cursor y los cambios inmediatos hechos en él (como un move_to sobre un objeto ya animado), e incluye a los descendientes. La geometría que los objetos reactivos regeneran en cada fotograma se mide como se declaró. Medir un objeto recién creado, antes del siguiente play o wait y sin nada que actúe sobre él (animaciones, grupos posteriores, layouts), cuesta alrededor de un milisegundo: se compila solo su declaración y la de sus miembros o referencias de next_to/align_to que cumplan lo mismo. En cualquier otro caso se compila la escena escrita hasta ese punto. Las mediciones sin nada escrito entre ellas comparten una compilación, y también los miembros de un mismo layout recién creado, así que conviene medir antes de animar y medir juntas las cajas que necesites. Una medición posterior reanuda esa compilación desde el segmento donde cambió la escena, como una recarga del editor, y la siguiente ejecución del script reanuda la última; un segmento con funciones de Python (reactivas, updaters) no se reutiliza entre ejecuciones. Lanza ValueError si el objeto no tiene geometría en el cursor. Sustituye a scene.text.measure.
Devuelve: Bounds — x e y (el centro), left, right, bottom, top, width, height y center en unidades de escena.
Convierte un píxel de una imagen o un vídeo en un punto de anclaje que sirve en move_to, scene.camera.inset, pan_to o conectores, y que sigue a la imagen si se mueve, escala o gira. Tiene en cuenta el recorte, width= y el modo de ajuste; mide sobre el archivo original, no sobre una captura reducida. Lanza ValueError en otros objetos o con coordenadas no finitas.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
px, py
float
obligatorio
Píxel del archivo original, contado desde la esquina superior izquierda con y hacia abajo, como en un editor de imágenes.
Devuelve: AnchorPoint — El punto de la imagen o el vídeo en ese píxel.
Fija el pivote de rotación, escala y sesgo en coordenadas de escena. Úsalo para bisagras y brazos que giran alrededor de un extremo. Sin él, el pivote es el centro de la caja en las figuras declaradas con coordenadas de escena (line, polygon, arcos, flechas y curvas) y el origen propio en las demás, que en circle, rect o text también es su centro. Una vez mostrado el objeto, el pivote cambia en el cursor sin moverlo y vale para las animaciones siguientes. En una parte de un SVG el punto también está en coordenadas de escena, aunque el SVG esté escalado o movido. pivot(x, y) es un alias.
Ejemplo
from gaanim import BLUE, GOLD, Scene
from math import pi
scene =Scene(frame=(16, 9), background="#0f172a")
hinge = scene.geometry.dot(0.09).fill(GOLD).move_to(-2.5, 1.25)
arm = scene.geometry.rect(1.125, 0.225).fill(BLUE).move_to(hinge).with_pivot(-2.5, 1.25)
scene.play([arm.animate.rotate_by(pi/2.5).duration(1.0)])
scene.render()
Copia el objeto tal como está declarado: forma, estilo, efectos y posición, con copias de sus miembros y, en un SVG importado, de sus partes con nombre (copia.part("cabeza") es la cabeza de la copia). No copia animaciones ni updaters, y los cambios posteriores de uno no llegan al otro. La copia se dibuja encima de lo declarado antes. Sirve para fantasmas o reflejos de un personaje sin importar el SVG varias veces.
Devuelve: Drawable — Un objeto nuevo e independiente; la copia de un Text es un Text.
Coloca un objeto libre respecto a otro o a los bordes del área segura. Los hijos de un Layout no usan estos métodos: su posición la decide el contenedor (ver Layout).
Define un anclaje local con nombre y devuelve el mismo objeto. El puerto sigue los límites, el reflow y las transformaciones de los padres. Los nombres son únicos e inmutables: vacíos, repetidos u offsets no finitos lanzan ValueError.
Desenfoque gaussiano de sigma unidades de escena; blur(0) lo quita. Después del primer play o wait es un corte en el cursor, como fill. Un sigma negativo o no finito lanza ValueError.
Dibuja el objeto y sus descendientes en una textura propia, le aplica los pases y devuelve el resultado a la escena en su lugar del orden de dibujo. Es un PostProcess.shader sobre un solo objeto: en el shader, gaanim_scene(uv) lee solo ese objeto (transparente alrededor), uv va de 0 a 1 sobre su caja con el margen, resolution es el tamaño de la textura en píxeles y time es el tiempo de la escena. Los uniforms aceptan Parameter, Computed y señales de audio. Los presets de PostProcess (grain, chromatic_aberration…) también sirven. Es estado de declaración: vale para toda la línea de tiempo. Si un objeto con efecto contiene otro, se aplica el efecto exterior. Se ve en la vista previa, en la exportación y en los paquetes .gaanim, que guardan los uniforms de cada fotograma.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
effect
PostProcess | Sequence[PostProcess] | None
obligatorio
Un pase o una cadena de pases WGSL; None quita el efecto.
margin
float
0.25
Unidades de escena que se agregan alrededor del objeto, para efectos que se salen de su contorno (un brillo, una onda).
Ejemplo
from gaanim import GOLD, WHITE, PostProcess, Scene
scene =Scene(frame=(16, 9), background="#0b1020")
ripple = PostProcess.shader("""fn gaanim_post(uv: vec2<f32>, resolution: vec2<f32>, time: f32) -> vec4<f32> { let wave = gaanim_uniforms.amount * sin(uv.x * 14.0 + time * 6.0); return gaanim_scene(uv + vec2<f32>(0.0, wave));}""", uniforms={"amount": 0.12})
title = scene.text("Ondas").fill(WHITE).scale_to(2.0).shader_effect(ripple, margin=0.4)
plain = scene.text("Sin efecto").fill(GOLD).scale_to(1.0).move_to(0, -2.5)
scene.wait(2)
scene.render()
Muestra el objeto y sus descendientes solo a través de source, como un track matte de After Effects. Con "alpha" se ve donde source es opaco (una foto o un degradado dentro de las letras de un título); con "luma", donde source es claro (un rectángulo con degradado que avanza hace un revelado suave); los modos invertidos muestran lo contrario. El mate sigue a source cuando se mueve, escala, aparece o se escribe, pero source deja de dibujarse por sí mismo. Un source desenfocado (blur, blur_in) suaviza el mate, no el objeto: los bordes de sus partes siguen nítidos dentro de la zona suave, así que unas barras enmascaradas por un texto que entra con blur_in se ven enteras donde un glifo aún es una mancha. Para que el resultado entre suave, funde source con animate.opacity o desenfoca el objeto. Es estado de declaración, vale para toda la línea de tiempo y se ve en la vista previa, la exportación y los paquetes .gaanim. Un source de otra escena, el propio objeto o un modo desconocido lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
source
Drawable | None
obligatorio
El mate: el objeto cuya forma o brillo deja ver a este; None quita el mate.
mode
str
"alpha"
"alpha", "alpha_inverted", "luma" o "luma_inverted".
Ejemplo
from gaanim import CORAL, GOLD, WHITE, Scene
scene =Scene(frame=(16, 9), background="#0b1020")
title = scene.text("MATE").fill(WHITE).scale_to(3.0)
stripes = scene.geometry.group([
scene.geometry.rect(0.5, 3).fill(color).no_stroke().move_to(-3.5+0.5* i, 0)
for i, color inzip(range(15), [GOLD, CORAL, "#22d3ee"] *5)
])
stripes.matte(title)
scene.play([title.animate.write().duration(1.5)])
scene.render()
Convierte el objeto en vidrio. Dentro de su contorno se ve el lienzo y todo lo que se dibujó antes, desenfocado y saturado. El contorno es una lente con un borde redondeado de ancho bevel: ahí lo que hay detrás se curva, se separa en colores y recibe un brillo. El borde sigue el contorno real de cualquier forma, metaballs incluidos. El objeto se dibuja encima, así que un relleno translúcido tiñe el vidrio y un trazo lo enmarca; el vidrio aparece y se desvanece con él. liquid_glass() es el mismo vidrio con valores de Liquid Glass (refraction=1.0, dispersion=0.12, bevel=0.6, blur=0.04, edge=0.8, saturation=1.4, transparency=0.92, twist=0.6): casi sin desenfoque, con el centro plano, un borde ancho que se empina hacia el contorno, curva con fuerza lo que hay detrás y lo desliza a lo largo del contorno, y una línea fina de luz en el contorno. Con un relleno claro ("#ffffff26") se ve como en iOS. backdrop_blur(radius, saturation=1.0) es solo el desenfoque, y no_glass() quita el efecto. Es estado de declaración y se ve en la vista previa, la exportación y los paquetes .gaanim. Valores negativos o no finitos, o edge, dispersion o transparency mayores que 1, lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
blur
float
0.25
Desenfoque de lo que hay detrás, en unidades de escena (la sigma de una gaussiana).
saturation
float
1.4
Saturación de esos colores; 1 los deja igual.
refraction
float
0.08
Cuánto se curva hacia dentro, en el borde, lo que hay justo fuera, en unidades de escena.
edge
float
0.3
Brillo del borde, con la luz arriba a la izquierda, de 0 a 1.
dispersion
float
0.0
Aberración cromática: cuánto se separan el rojo, el verde y el azul en el borde, de 0 a 1.
bevel
float
0.12
Ancho del borde redondeado de la lente, en unidades de escena; hacia dentro el vidrio es plano y no deforma.
twist
float
0.0
Desliza lo que muestra el borde a lo largo del contorno, como fracción de la curvatura, de −2 a 2: positivo gira en sentido horario (hacia la derecha arriba y hacia la izquierda abajo), como en Liquid Glass.
transparency
float
1.0
Cuán claro es el vidrio, de 0 a 1: 1 deja ver lo que hay detrás, valores menores lo vuelven lechoso y 0 es blanco opaco.
Ejemplo
from gaanim import BLUE, CORAL, GOLD, Scene
scene =Scene(frame=(16, 9), background="#0b1020")
for i, color inenumerate([BLUE, GOLD, CORAL]):
scene.geometry.circle(1.3).fill(color).no_stroke().move_to(-2.5+2.5* i, 0.4* (-1) ** i)
card = scene.geometry.rounded_rect(5, 3, 0.4).fill("#ffffff1a").stroke("#ffffff55", 0.03).move_to(-3, 1)
card.glass(blur=0.25, refraction=0.14)
drops = [scene.geometry.circle(0.9).move_to(x, -2.2) for x in (-2.5, 2.5)]
lens = scene.geometry.metaballs(drops, smoothness=0.9).fill("#ffffff10").liquid_glass()
scene.play([card.animate.move_to(3, 1).duration(2.0), drops[0].animate.move_to(1.0, -2.2).duration(2.0)])
scene.render()
Sombra proyectada desplazada y desenfocada. En un texto o un grupo, una sombra desenfocada se dibuja una sola vez a partir de la silueta de sus miembros rellenos y debajo de todos, como drop-shadow de CSS sobre un grupo: los solapes no se oscurecen y el coste no crece con cada glifo. Los miembros recortados, con mezcla o solo con trazo proyectan la suya.
Pone puntas de flecha o puntos en los extremos de cualquier trazo: polilíneas, curvas, arcos o conectores con via. Se rellenan con el color del trazo y siguen a los extremos actuales del camino, así que acompañan a trim, create() y a los caminos que se regeneran; animate.grow_arrow() dibuja el trazo desde la cola con la punta delante. El vértice de la flecha es el extremo del camino y el trazo termina bajo su base. Si el camino es más corto que la punta, esta se encoge con él. tip(None) las quita. Un tipo desconocido o un tamaño no positivo lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
end / start
"arrow" | "dot" | None
"arrow" / None
Punta de cada extremo del camino.
length
float | None
None
Largo de la punta de flecha; por defecto, cinco grosores de trazo y al menos 0.15.
width
float | None
None
Ancho de la base de la flecha (0.9 del largo) o diámetro del punto (tres grosores de trazo).
Ejemplo
from gaanim import CYAN, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
route = scene.geometry.polyline([(-5, -1.5), (-2, 1.5), (2, -1.5), (5, 1.5)]).no_fill()
route.stroke(CYAN, 0.06).tip(end="arrow", start="dot")
scene.play([route.animate.grow_arrow().duration(1.5)])
scene.render()
Modo de fusión con lo que hay debajo. "screen" y "add" aclaran (luces, destellos), "multiply" oscurece como tinta (resaltadores) y "normal" vuelve a pintar encima, también en un miembro de un grupo con otro modo. Como fill, en un grupo o un Text llega a todos sus miembros; un miembro al que le cambias el modo después conserva el suyo. El objeto se pinta en su propia capa, así que dentro de un recorte, un grupo con opacidad o una transición solo se funde con el contenido de ese grupo. No se anima. Un modo desconocido lanza ValueError.
Copias que siguen al objeto en el tiempo, como el efecto Echo de After Effects: la copia k lo muestra como estaba hace k * delay segundos, con decay ** k de su opacidad y debajo de él. Cada copia repite las animaciones del propio objeto (animate, create, fundidos, color y forma) con ese retraso, así que es exacta en cualquier búsqueda y en todas las exportaciones, SVG incluido. Se ocultan mientras el objeto está oculto y no cruzan un corte de segmento. No retrasan el movimiento de los updaters, de las posiciones reactivas ni de un grupo padre que se mueve, ni copian Lottie o vídeo. En un Text, cada glifo repite sus propias animaciones. Se declara una vez y vale para toda la línea de tiempo.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
count
int
5
Copias, de 1 a 32; 0 quita el eco.
delay
float
0.04
Segundos entre copias; positivo.
decay
float
0.6
Opacidad de cada copia respecto a la anterior, en (0, 1].
hold
bool
False
Con True las copias se retrasan a lo largo del movimiento y no del reloj: cuando el objeto se detiene, quedan congeladas donde estaban (papel cebolla) y siguen cuando vuelve a moverse. Sin él, alcanzan al objeto al detenerse y dejan de dibujarse: una copia que coincide con el objeto no se apila sobre él, así que un objeto translúcido en reposo se ve igual que sin eco.
start / end
float | None
None
Segundos de la escena que graban las copias: cada copia muestra el objeto solo como estaba entre start y end, y se oculta fuera de ese intervalo. Así la estela crece desde start, se vacía después de end y no aparece en el resto de movimientos. Cualquiera de los dos puede quedar abierto; end debe ser mayor que start.
Ejemplo
from gaanim import CORAL, GOLD, Scene
scene =Scene(frame=(16, 9), background="#0e1422")
ball = scene.geometry.circle(0.45).fill(CORAL).move_to(-6, 0).echo(6, delay=0.05, decay=0.7)
scene.play([ball.animate.move_to(6, 0).duration(1.2)])
scene.play([ball.animate.move_to(0, 0).fill(GOLD).duration(0.6)])
scene.render()
from gaanim import CORAL, Scene
scene =Scene(frame=(16, 9), background="#0e1422")
# La estela solo existe durante la sacudida, de 1.0 s a 1.6 s.
head = scene.geometry.circle(0.6).fill(CORAL).move_to(-4, 0).echo(6, delay=0.04, start=1.0, end=1.6)
scene.play([head.animate.move_to(0, 0).duration(1.0)])
scene.play([head.animate.wiggle().duration(0.6)])
scene.play([head.animate.move_to(4, 0).duration(1.0)])
scene.render()
Muestra las primeras count copias de un grupo creado con Geometry.repeat o Geometry.duplicate; las demás siguen en el grupo pero ocultas, de la última hacia atrás. Un recuento fraccionario funde la siguiente copia: 2.5 muestra dos copias y media tercera. Antes del primer scene.play fija el recuento inicial; después lo cambia en el cursor. Para animarlo usa animate.count. Un valor fuera de rango, o un objeto que no sea uno de esos grupos, lanza ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
count
float
obligatorio
Copias visibles, de 0 al número de copias del grupo.
Ejemplo
ring = scene.geometry.duplicate(scene.geometry.dot(0.1), Distribution.circle(16, 2.5)).count(4)
Fija todos los vértices de un polígono o una polilínea. Antes del primer scene.play cambia la forma declarada, así que varias figuras pueden nacer iguales y deformarse luego; después la cambia en el cursor. animate.points sigue desde ahí. Una polilínea con closed=True sigue cerrada. Otro número de puntos, un valor no finito, un objeto que no sea polígono ni polilínea o una polilínea con coordenadas reactivas lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
points
Sequence[tuple[float, float]]
obligatorio
Un punto por vértice, en las coordenadas en que se declaró la figura.
Estira el objeto en la dirección de su velocidad y lo aplasta en la perpendicular, conservando el área: el estiramiento es 1 + amount * velocidad, como mucho max_ratio, y el aplastamiento su inverso. La velocidad sale de las animaciones del propio objeto medidas en t ± 1/60 s, así que un objeto quieto nunca se deforma y las búsquedas son exactas. Los miembros de un grupo se deforman con él. No cuentan el movimiento de los updaters, las posiciones reactivas ni un padre que se mueve. Un amount negativo o un max_ratio menor que 1 lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
amount
float
0.1
Estiramiento por unidad de velocidad (unidades de escena por segundo); 0 quita el efecto.
max_ratio
float
1.6
Estiramiento máximo, al menos 1.
Ejemplo
from gaanim import CORAL, Scene
scene =Scene(frame=(16, 9), background="#0f1729")
ball = scene.geometry.circle(0.5).fill(CORAL).move_to(-6, 0).squash_stretch(0.08, max_ratio=1.8)
scene.play([ball.animate.move_to(6, 0).duration(1.0)])
scene.play([ball.animate.move_to(0, -2.5).duration(0.5)])
scene.render()
Trazo de grosor variable, como los perfiles de ancho de Illustrator: el ancho se interpola linealmente entre los puntos, así que [(0, 0), (0.5, 1), (1, 0)] se ensancha en el centro y termina en punta. El trazo se dibuja como un contorno relleno: no admite guiones, pero trim, create y show_passing_flash recortan la parte visible y el perfil se ajusta a ella, así que un destello afinado sigue acabando en punta. En un grupo o un Text llega a todos sus miembros. Una posición fuera de [0, 1] o un factor negativo lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
profile
Sequence[tuple[float, float]] | None
obligatorio
Pares (posición, factor): posición en [0, 1] de la longitud visible y factor del ancho del trazo; None vuelve al trazo normal.
Ejemplo
import math
from gaanim import CORAL, GOLD, TEAL, Scene
scene =Scene(frame=(16, 9), background="#101826")
brush = scene.geometry.arc(-4, 0, 2.0, 0.3, 4.2).no_fill().stroke(GOLD, 0.35).stroke_taper(0.35, 0.5)
wave = scene.geometry.polyline([(x /10, 1+0.6* math.sin(x /4)) for x inrange(-10, 61)])
wave.stroke(TEAL, 0.3).stroke_profile([(0.0, 0.1), (0.5, 1.0), (1.0, 0.1)])
flash = scene.geometry.polyline([(-1, -2.2), (2, -1.2), (5, -2.6), (7, -1.8)]).stroke(CORAL, 0.25).stroke_taper(0.5, 0.5)
scene.play([brush.animate.create(), wave.animate.create()])
scene.play([flash.animate.show_passing_flash(time_width=0.5)])
scene.render()
Atajo de stroke_profile para pinceladas y flechas caligráficas.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
start / end
float
0.2
Fracción de la longitud visible en la que el trazo se afina hasta una punta, al principio y al final; start + end <= 1.
Anotaciones a mano alzada
PROPIEDADDrawable.annotateannotate: Annotations
Subrayados, cajas, círculos, tachados y corchetes con trazo de mano alzada, al estilo de rough-notation. Cada método devuelve un Drawable nuevo con trazo: las líneas tiemblan y se arquean como dibujadas a mano, y la forma se dibuja passes veces sobre sí misma con otro azar. La marca sigue los límites del objetivo en cada fotograma, conserva su garabato cuando el objetivo se mueve y permanece oculta hasta que un play la incluye, así que marca.animate.create() la dibuja pasada a pasada. Se puede desvanecer o reestilizar como cualquier drawable, pero se mueve moviendo su objetivo. La misma seed dibuja siempre el mismo garabato. También existe en las selecciones de texto (TextSelection.annotate); para resaltar con rotulador usa TextSelection.marker.
Devuelve: Annotations — Constructor de anotaciones alrededor de este drawable.
Ejemplo
from gaanim import*
scene =Scene(frame=(16, 9))
title = scene.text("Anotaciones", role="title").move_to(0, 2.6)
card = scene.geometry.rounded_rect(3.2, 1.6, 0.2).fill(BLUE).move_to(-3.2, -0.6)
word = scene.text("importante").move_to(3.2, -0.6)
ul = title.annotate.underline(color=RED, seed=1)
box = card.annotate.box(color=GOLD, seed=2)
circle = word.annotate.circle(color=RED, seed=3)
scene.play([ul.animate.create(), box.animate.create()], duration=1.2)
scene.play([circle.animate.create()], duration=0.9)
scene.render()
MÉTODOAnnotations.underline / box / circle / strike_through / crossed_off
underline traza una línea bajo el objetivo (por defecto 0.08 por debajo y 0.04 a cada lado), box una caja (0.1 por lado), circle una elipse que pasa por el centro de cada lado acolchado (0.25 arriba y abajo, 0.35 a los lados), strike_through una línea por el centro (0.06 a cada lado) y crossed_off las dos diagonales (0.05 por lado). Un roughness o padding negativo o no finito, passes fuera de 1 a 8 o un width no positivo lanzan ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
color
ColorLike | None
None
Color del trazo; sin color se usa el trazo del tema.
width
float | None
None
Grosor del trazo; requiere color.
roughness
float
1.0
Escala del temblor: 0 dibuja geometría limpia y 1 el aspecto de rough-notation.
passes
int
2
Veces que se dibuja la forma, de 1 a 8.
seed
int
0
Semilla del garabato.
padding
Padding | None
None
Crecimiento de los límites del objetivo: escalar, (vertical, horizontal) o (arriba, derecha, abajo, izquierda).
Devuelve: Drawable — La marca, oculta hasta que un play la incluye.
Corchetes a mano alzada en los lados elegidos; acepta los demás argumentos de underline, con padding de 0.05 arriba y abajo y 0.1 a los lados. Un lado desconocido lanza ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
sides
str | Sequence[str]
("left", "right")
Lados con corchete: "left", "right", "top" o "bottom".
Devuelve: Drawable — Los corchetes, ocultos hasta que un play los incluye.
Modificadores no destructivos, como los operadores de forma de After Effects y Lottie: cada método añade uno a partir del cursor y lo devuelve, y sus números se animan con modificador.animate. Se aplican en el orden en que se añadieron, sobre el trazado ya animado (recortes, write, morph) y justo antes de dibujarlo, a cada miembro con trazado de un grupo o un Text. bounds() y el layout siguen midiendo la forma original. Un trazado abierto puede ganar área; las primitivas abiertas (line, arc, polyline, traced_path…) nacen sin relleno, así que solo se ve el trazo hasta que le des uno con fill().
Devuelve: PathModifiers — La pila de modificadores de trazado del objeto.
El giro se desvanece hasta cero en el vértice más lejano del centro.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
angle
float
obligatorio
Giro en el centro, en radianes. Animable.
Devuelve: PathModifier — El modificador, que anima angle.
MÉTODOPathModifiers.wiggle_pathwiggle_path(size: float = 0.1, *, detail: int = 6, frequency: float = 1.0, seed: int = 0) -> PathModifier
Contorno vivo con ruido coherente con semilla, desde el instante en que se añade; los puntos se unen con curvas suaves. La misma semilla da la misma forma en el mismo tiempo, así que un seek es exacto.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
size
float
0.1
Desplazamiento máximo a lo largo de la normal, en unidades. Animable.
detail
int
6
Puntos por segmento, de 1 a 256.
frequency
float
1.0
Cambios por segundo. Animable.
seed
int
0
Semilla del ruido.
Devuelve: PathModifier — El modificador, que anima size y frequency.
Agranda o encoge las formas cerradas; encoger más allá del radio interior no deja nada. Un trazado abierto se vuelve una banda de |amount| a cada lado. Las copias forman un solo trazado, así que un trazo alineado por dentro (el predeterminado) solo muestra la mitad interior del anillo exterior: para anillos usa align="center".
Parámetros
Nombre
Tipo
Predeterminado
Descripción
amount
float
obligatorio
Unidades hacia fuera, o hacia dentro si es negativo. Animable.
join
"miter" | "round" | "bevel"
"miter"
Cómo gira el contorno en las esquinas.
copies
int
1
Contornos a amount, 2 * amount, …, de 1 a 64.
Devuelve: PathModifier — El modificador, que anima amount.
Anima los números del modificador como cualquier otra animación. Un nombre que el modificador no tiene lanza ValueError; PathModifier.names los enumera y PathModifier.set(size=0.2) los cambia de golpe desde el cursor.
Devuelve: PathModifierAnimation — Métodos size, radius, amount, angle y frequency, que devuelven un Anim.
Si el desenfoque de movimiento de la escena lo difumina. Con False, cada subcuadro lo dibuja como está en el tiempo del cuadro, por ejemplo para un título o un HUD que no deben emborronarse mientras todo lo demás se mueve. Las copias de echo heredan el ajuste.
Si el postprocesado de la escena, o el de su segmento, se aplica al objeto. Con False se dibuja encima del cuadro ya procesado, por ejemplo una etiqueta o un HUD que pixelate, glitch o halftone harían ilegibles. Queda encima de todo lo procesado, sea cual sea su z_index, y sigue las transiciones de su segmento; en una transición por shader se funde con su progreso. Las copias de echo heredan el ajuste.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
enabled
bool
True
False deja fuera del postprocesado el objeto y sus miembros.
Ejemplo
from gaanim import CORAL, PostProcess, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
scene.canvas.post = PostProcess.pixelate(24)
scene.geometry.circle(2).fill(CORAL).move_to(-3, 0)
scene.text("pixelado", size=0.9).move_to(-3, -3)
scene.text("legible", size=0.9).move_to(3, -3).post_process(False)
scene.wait(0.5)
scene.render()
Muestra solo una parte del trazo, como los trim paths de After Effects. Los valores omitidos conservan el ajuste anterior. Anímalo con animate.trim(...).
Parámetros
Nombre
Tipo
Predeterminado
Descripción
start / end
float | None
None
Ventana visible del camino como fracción de su longitud; al principio valen 0 y 1.
offset
float | None
None
Desplaza la ventana; da la vuelta al final del camino.
mode
str | None
None
"simultaneous" (predeterminado) recorta cada subcamino a la vez; "sequential" recorta la longitud total y los subcaminos aparecen uno tras otro.
Ejemplo
from gaanim import GOLD, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
ring = scene.geometry.circle(1.5).no_fill().stroke(GOLD, 0.08).trim(end=0.0)
scene.play([ring.animate.trim(end=1.0).duration(1.0)])
scene.play([ring.animate.trim(start=0.7, offset=0.5).duration(0.8)])
scene.render()
Recorte vectorial vivo: la máscara puede moverse, escalarse o rotar y el recorte se recalcula en cada fotograma. La máscara sigue visible; usa no_fill().no_stroke() si solo debe definir la silueta. Una regla desconocida lanza ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
mask
Drawable
obligatorio
Silueta vectorial que recorta este objeto.
rule
str
"nonzero"
Regla de relleno de la máscara: "nonzero" o "evenodd".
invert
bool
False
Recorta al exterior de la máscara.
Ejemplo
from gaanim import BLUE, GOLD, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
stripes = scene.geometry.group([
scene.geometry.rect(0.4, 4).fill(GOLD if i %2else BLUE).move_to(-3+0.4* i, 0)
for i inrange(16)
])
lens = scene.geometry.circle(1.2).no_fill().no_stroke().move_to(-2, 0)
stripes.clip(lens)
scene.play([lens.animate.move_to(2, 0).duration(1.2)])
scene.render()
MÉTODODrawable.no_clipno_clip() -> Drawable
Quita el recorte por máscara. En las marcas de datos de un espacio cartesiano, deja que la marca sobresalga del área de trazado.
Convierte esta figura en una pantalla que muestra lo que ve una segunda cámara, como un picture-in-picture o una lupa. La pantalla dibuja su relleno, encima la vista recortada a su contorno y encima su trazo; la opacidad y los fundidos afectan a todo. La vista no muestra la pantalla, el marco, exclude ni las superposiciones HUD; una pantalla que aparece dentro de otra vista muestra su pintura pero no su vista. Solo una figura cerrada 2D puede ser pantalla (rectángulo, cuadrado, círculo, punto, elipse, polígono, estrella, sector, anillo, curva, camino SVG o booleano). Lanza ValueError con texto, grupos, imágenes u objetos 3D, con frame igual a la propia pantalla, con objetos o parámetros de otra escena, con un zoom no positivo, con un nombre de capa vacío o con un fit o background desconocido. Una llamada posterior o no_camera_view() sustituye la vista.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
frame
Drawable | None
None
Objeto que hace de cámara: su centro marca adónde mira y su giro gira la vista en sentido contrario. Sin zoom, su tamaño también fija el aumento, así que reducirlo acerca. Sin frame, la cámara mira a través de un marco invisible.
center
tuple | Drawable | AnchorPoint | None
None
Adónde mira la cámara cuando no hay frame: un punto, el centro de un objeto o un punto de anclaje; por defecto, el origen. Con frame lanza ValueError.
zoom
float | Parameter | Computed | None
None
Aumento fijo en lugar del tamaño del marco. Un número da a la vista su propio zoom, que animate.zoom_to cambia a velocidad percibida constante; un Parameter se anima de forma lineal; un Computed se sigue y no se puede fijar. Sin frame ni zoom, vale 1.
fit
str
"contain"
Con un aumento dado por el marco: "contain" muestra el marco entero, "cover" llena la pantalla y "stretch" escala cada eje por separado.
background
Paint | str | None
"canvas"
Fondo de la vista: "canvas" pinta el fondo de la escena tal como lo ve la cámara, un color o Brush pinta la pantalla y None deja ver el relleno propio de la pantalla.
exclude
Sequence[Drawable]
()
Objetos, con sus hijos, que la vista no muestra.
layers
Sequence[str]
()
Capas de vista (ver view_layer) que la vista muestra además de los objetos normales.
Devuelve: CameraView — La cámara, con pan_to, zoom_to, rotate_to, follow y animate; ver Escena.
Ejemplo
from gaanim import BLUE, GOLD, WHITE, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
for i inrange(40):
scene.geometry.dot(0.04).fill(GOLD if i %3else BLUE).move_to(-6+0.15* i, 0.4* (i %4) -0.6)
frame = scene.geometry.rect(1.6, 0.9).no_fill().stroke(GOLD, 0.03).move_to(-5, 0)
screen = scene.geometry.rounded_rect(6.4, 3.6, 0.2).stroke(WHITE, 0.05).move_to(3.5, 0)
screen.camera_view(frame)
scene.play([frame.animate.move_to(-1.5, 0).duration(1.2)])
scene.play([frame.animate.scale_to(0.5).duration(0.8)])
scene.render()
Pone el objeto y sus hijos en una capa de vista: la cámara principal no lo dibuja y solo lo muestran las vistas de cámara que listan esa capa en layers. Sirve para una lupa de rayos X que revela lo que hay debajo, o para etiquetas que solo aparecen en el zoom. Un nombre vacío lanza ValueError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
name
str | None
obligatorio
Nombre de la capa; None devuelve el objeto a ninguna capa.
Ejemplo
from gaanim import GOLD, WHITE, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
scene.geometry.rounded_rect(6, 3, 0.4).fill("#334155").no_stroke()
for x in (-2, 0, 2):
scene.geometry.circle(0.5).fill(GOLD).no_stroke().move_to(x, 0).view_layer("xray")
lens = scene.geometry.circle(1.2).stroke(WHITE, 0.05).move_to(-3, 0)
view = lens.camera_view(center=(-3, 0), layers=["xray"])
scene.play([lens.animate.move_to(3, 0).duration(2.0), view.animate.pan_to(3, 0).duration(2.0)])
scene.render()
Animación
El proxy que convierte los setters en animaciones y las acciones de modelos importados.
PROPIEDADDrawable.animateanimate: Anim
Proxy puro de animación compuesta. Encadena destinos de transformación, opacidad, relleno, trazo, color o material; todos comparten duración y easing y corren a la vez. El resultado es un Anim que no cambia nada hasta pasarlo a scene.play.
Gaanim ya no importa glTF, así que tampoco reproduce sus acciones: Drawable.animations() devuelve una tupla vacía y Drawable.animation(name, ...) lanza NotImplementedError. part y parts están en Medios.
Relaciones reactivas
Hacen que un objeto siga a otro en el mismo fotograma sin callbacks de Python. El seguidor queda oculto hasta su animación de entrada. Para simulaciones y series muestreadas, consulta add_updater_fn y drive_from_samples en Animaciones.
Sigue cualquier extremo en el mismo fotograma y devuelve el objeto. Con delay copia al líder con retardo, como valueAtTime(time - delay) de After Effects: encadena seguidores con retardos crecientes para estelas y colas (overlapping action). Las animaciones del líder se evalúan de nuevo en t - delay en cada fotograma, así que un seek a cualquier instante reproduce la estela sin estado acumulado. El líder puede seguir a su vez a otro objeto (follow con o sin retardo, follow_to, attach_to), así que los seguidores de seguidores forman cadenas; hasta que el segmento actual lleva delay segundos, el seguidor espera en la posición del líder al inicio del segmento. Offsets o retardos no finitos, retardos negativos o modos inválidos lanzan ValueError; un retardo positivo con una fuente que no es Drawable lanza TypeError.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
source
Endpoint
obligatorio
Drawable, AnchorPoint, PointRef o tupla.
offset
tuple[float, float]
(0.0, 0.0)
Desplazamiento respecto a la fuente.
offset_space
str
"world"
"world" mantiene el desplazamiento alineado con la pantalla; "local" lo rota y escala con la fuente.
delay
float
0.0
Segundos de retardo: el objeto va donde estaba source hace delay segundos. Con un valor positivo source debe ser un Drawable.
Ejemplo
from gaanim import GOLD, WHITE, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
theta = scene.viz.parameter(0.2)
tip = scene.geometry.polar_point((0, 0), 1.5, theta)
bar = scene.mechanics.bar_between((0, 0), tip).stroke(WHITE, 0.09)
label = scene.text("punta").fill(GOLD).follow(tip, offset=(0, 0.225))
scene.play([bar.animate.fade_in(), label.animate.write(), theta.animate.set(2.2).duration(1.4)])
scene.render()
Una cola que sigue al líder con retardo:
from gaanim import CORAL, GOLD, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
leader = scene.geometry.circle(0.35).fill(GOLD).move_to(-5, 0)
dots = [scene.geometry.circle(0.25-0.04* i).fill(CORAL) for i inrange(5)]
for i, dot inenumerate(dots):
dot.follow(leader, delay=0.06* (i +1))
scene.play([dot.animate.fade_in().duration(0.01) for dot in dots])
scene.play(leader.animate.move_to(5, 1.5).duration(1.2))
scene.play(leader.animate.move_to(0, -2).duration(0.8))
scene.wait(0.5)
scene.render()
Coloca el objeto sobre el centro de source y lo sigue mientras se mueve. Para mantener una separación usa follow_to o follow. Devuelve None, así que llámalo en su propia línea.
Ejemplo
from gaanim import GOLD, Scene
scene =Scene(frame=(16, 9), background="#0f172a")
from gaanim import WHITE
mass = scene.geometry.dot(0.15).fill(GOLD).move_to(-1.5, 0)
ring = scene.geometry.circle(0.4).no_fill().stroke(WHITE, 0.04)
ring.attach_to(mass)
scene.play([ring.animate.create().duration(0.3), mass.animate.shift_by(3, 0).duration(1.2)])
scene.render()
Copia la coordenada X, la Y o ambas de source en cada fotograma, donde quiera que esté: animada, movida por un updater o colocada con follow(...). axes acepta "x", "y" o "xy". Útil para proyecciones sobre un eje. Devuelven None.
Copia la rotación mundial de source como rotación * ratio + phase, en radianes. Es la base del acoplamiento de engranajes. Cuenta la rotación de source y de sus padres, también la de un Updater.rotate y la de un rotate_to(Parameter).
Traslada el objeto a lo largo de axis según el giro acumulado de source multiplicado por scale, como una cremallera movida por un piñón. Cuenta las vueltas completas de un rotate_to(Parameter) y de un Updater.rotate; las demás rotaciones, hasta dos vueltas en cada sentido. Es una relación visual, no un solver de contacto.
Coloca el objeto en una posición del mundo 3D. Añade .billboard() para que una etiqueta mire siempre a la cámara o .hud() para fijarla a la pantalla. Acepta fuentes reactivas.
Mantiene un objeto 3D orientado hacia la cámara en perspectiva. Útil para etiquetas y marcadores.
MÉTODODrawable.hudhud() -> Self
Fija el objeto a la imagen como superposición: se queda en su sitio aunque la cámara 2D se desplace, acerque o gire, y aunque se mueva la cámara 3D. Sus coordenadas son las de la cámara sin mover, así que .move_to(0, 3.5) lo pone arriba en un fotograma de 16 × 9. Se dibuja encima de la escena y nunca aparece dentro de una vista de cámara. Pertenece a su segmento como cualquier objeto: wipe, iris, blinds y las demás transiciones vectoriales lo recortan con su segmento, y push y slide lo desplazan con él. En cross_fade, fade_through y zoom_through, que solo funden la opacidad, se ven a la vez el HUD del segmento que sale y el del que entra; si deben ocupar el mismo sitio, usa un solo HUD con scene.persist(...) y cambia su contenido, o dale al que entra una entrada que empiece al terminar la transición.
Ejemplo
title = scene.text("Modelo 3D", role="title").hud().move_to(0, 3.5)