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()
animation preview

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
NombreTipoPredeterminadoDescripción
paintPaintobligatorioColor, 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).
MÉTODODrawable.strokestroke(paint: Paint, width: float, *, align: Optional[Literal["inside", "center", "outside"]] = None, scale_with_object: Optional[bool] = None) -> Self
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
NombreTipoPredeterminadoDescripción
paintPaintobligatorioColor o Brush.
widthfloatobligatorioAncho 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.
alignstr | NoneNone"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_objectbool | NoneNoneTrue 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()
animation preview
MÉTODODrawable.scale_stroke_with_objectscale_stroke_with_object(enabled: bool = True) -> Self
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
NombreTipoPredeterminadoDescripción
enabledboolTrueFalse 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
NombreTipoPredeterminadoDescripción
seedint0Semilla del temblor y del grano: la misma semilla dibuja la misma tiza en cada fotograma y exportación.
roughnessfloat0.01Desplazamiento máximo del contorno, en unidades de escena; 0 deja el contorno limpio y solo aplica el grano.
Ejemplo
box = scene.geometry.rect(3, 1.5).no_fill().stroke(WHITE, 0.05).chalk(seed=2)
scene.play([box.animate.write().duration(1)])
MÉTODODrawable.no_strokeno_stroke() -> Self
Quita el trazo. Las flechas sólidas se ven mejor con .fill(color).no_stroke().
MÉTODODrawable.stroke_stylestroke_style(style: StrokeStyle) -> Self
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
NombreTipoPredeterminadoDescripción
styleStrokeStyleobligatorioPintura, ancho, extremo, unión, límite de inglete, guiones, desfase de guiones y alineación.
Ejemplo
from gaanim import Scene, StrokeStyle
scene = Scene(frame=(16, 9))
guide = scene.geometry.line(-2, 0, 2, 0).stroke_style(
    StrokeStyle("#2563eb", 5, cap="round", dashes=[18, 10])
)
scene.wait(0.1)
scene.render()
animation preview
MÉTODODrawable.style_classstyle_class(name: str) -> Self
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
NombreTipoPredeterminadoDescripción
namestrobligatorioClase 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()
animation preview
MÉTODODrawable.opacityopacity(op: ScalarSource) -> Self
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.
Parámetros
NombreTipoPredeterminadoDescripción
opfloat | Parameter | Variable | Computed | TimeInputobligatorioOpacidad de 0 a 1, o una fuente reactiva.
Ejemplo
ghost = scene.geometry.circle(1).fill(WHITE).opacity(0.3)
level = scene.viz.parameter(0.2)
halo = scene.geometry.circle(1.4).fill(GOLD).opacity(level)
scene.play([level.animate.set(1.0).duration(1)])
MÉTODODrawable.z_indexz_index(z: int) -> Self
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
NombreTipoPredeterminadoDescripción
zintobligatorioCapa 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.
Parámetros
NombreTipoPredeterminadoDescripción
namestrobligatorioUna de las capas nombradas con Scene.z_layers.
Ejemplo
scene.z_layers("modelo", "overlay")
muro = scene.geometry.rect(4, 3).fill(BLUE).z_index(400)
lupa = scene.geometry.circle(0.8).fill(GOLD).z_layer("overlay")
MÉTODODrawable.covers_on_purposecovers_on_purpose() -> Self
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.
Ejemplo
dialogo = scene.geometry.rect(4, 2).fill(WHITE).covers_on_purpose()
MÉTODODrawable.namednamed(name: str) -> Self
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
NombreTipoPredeterminadoDescripción
namestrobligatorioNombre 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
NombreTipoPredeterminadoDescripción
x / yfloat | fuente reactivaobligatorioPosición de destino en unidades de escena.
anchorAnchor | str | NoneNoneUn Anchor o su nombre, como "top_left". Punto propio que se coloca en (x, y); posicional o por nombre.
referenceDrawableobligatorioAlternativa: centra este objeto sobre otro.
pointAnchorPointobligatorioAlternativa: coloca el centro sobre un anclaje de otro objeto.
Ejemplo
box = scene.geometry.rect(3, 1.5).move_to(-4, 1, Anchor.TOP_LEFT)
label = scene.text("centro").move_to(box)
corner = scene.geometry.dot(0.1).move_to(box.anchor_point(Anchor.BOTTOM_RIGHT))
MÉTODODrawable.shift_byshift_by(dx: float, dy: float) -> Self
Traslada el objeto (dx, dy) unidades de escena respecto a su posición actual, como un corte inmediato en el cursor.
Ejemplo
dot = scene.geometry.dot(0.1).move_to(0, 0)
scene.wait(0.5)
dot.shift_by(1, 0.5)
MÉTODODrawable.scale_toscale_to(factor: ScalarSource) -> Self
Fija la escala uniforme absoluta alrededor del pivote (ver with_pivot). Acepta fuentes reactivas.
Ejemplo
logo = scene.media.svg("assets/logo.svg").scale_to(2.5)
MÉTODODrawable.scale_byscale_by(factor: float) -> Self
Multiplica la escala actual por factor en el cursor. Mayor que 1 agranda y menor que 1 reduce.
MÉTODODrawable.rotate_torotate_to(radians: ScalarSource) -> Self
Fija la rotación absoluta en radianes alrededor del pivote (ver with_pivot); los valores positivos giran en sentido antihorario. Acepta fuentes reactivas.
Ejemplo
tilted = scene.geometry.square(1).rotate_to(math.pi / 4)
MÉTODODrawable.rotate_byrotate_by(radians: float) -> Self
Suma radians a la rotación actual en el cursor.
MÉTODODrawable.skew_toskew_to(x: float, y: float) -> Self
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
NombreTipoPredeterminadoDescripción
xfloatobligatorioCorte horizontal: cada punto se desplaza en x x veces su altura sobre el pivote.
yfloatobligatorioCorte 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()
animation preview
MÉTODODrawable.matrix_tomatrix_to(matrix: tuple[tuple[float, float], tuple[float, float]]) -> Self
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
NombreTipoPredeterminadoDescripción
matrixtuple[tuple[float, float], tuple[float, float]]obligatorioFilas ((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()
animation preview
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.
Ejemplo
from gaanim import GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
label = scene.text("PGA = 0.35 g", role="label").move_to(-2, 1)
box = label.bounds()
frame = scene.geometry.rounded_rect(box.width + 0.56, box.height + 0.32, 0.14)
frame.no_fill().stroke(GOLD, 0.04).move_to(*box.center)
scene.play([frame.animate.create().duration(0.6)])
scene.render()
animation preview
MÉTODODrawable.pixelpixel(px: float, py: float) -> AnchorPoint
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
NombreTipoPredeterminadoDescripción
px, pyfloatobligatorioPí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.
Ejemplo
ui = scene.media.image("assets/cover.png", width=12)
view = scene.camera.inset(ui.pixel(812, 240), zoom=3)
MÉTODODrawable.with_pivotwith_pivot(x: float, y: float) -> Self
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()
animation preview
MÉTODODrawable.pivotpivot(x: float, y: float) -> Self
Alias de with_pivot.
MÉTODODrawable.copycopy() -> Drawable
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.
Ejemplo
robot = scene.media.svg("assets/robot.svg").scale_to(2)
ghost = robot.copy().opacity(0.3).shift_by(-1.5, 0)
ghost.part("head").fill(GOLD)

Posición relativa

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).

MÉTODODrawable.next_tonext_to(reference: Drawable, direction: Direction, spacing: float = 0.24, aligned_edge: Optional[AnchorName | Anchor] = None) -> Self
Coloca este objeto junto a otro sin superponerlos.
Parámetros
NombreTipoPredeterminadoDescripción
referenceDrawableobligatorioObjeto de referencia.
directionDirectionobligatorioLado donde se coloca este objeto.
spacingfloat0.24Separación entre bordes en unidades de escena.
aligned_edgeAnchor | str | NoneNoneBorde común que se alinea, como Anchor o por su nombre; None centra en el eje transversal.
Ejemplo
title = scene.text("Resultados", role="title")
rule = scene.geometry.line(length=4).next_to(title, Direction.DOWN, spacing=0.2)
note = scene.text("n = 42", role="caption").next_to(title, Direction.RIGHT, spacing=0.3, aligned_edge=Anchor.BOTTOM)
MÉTODODrawable.align_toalign_to(reference: Drawable, target_anchor: AnchorName | Anchor, reference_anchor: Optional[AnchorName | Anchor] = None) -> Self
Hace coincidir un anclaje propio con un anclaje de otro objeto.
Parámetros
NombreTipoPredeterminadoDescripción
referenceDrawableobligatorioObjeto de referencia.
target_anchorAnchor | strobligatorioAnclaje propio que se alinea.
reference_anchorAnchor | str | NoneNoneAnclaje de la referencia; None usa el mismo que target_anchor.
Ejemplo
panel = scene.geometry.rect(5, 3).move_to(1, 0)
tag = scene.slides.badge("NUEVO").align_to(panel, Anchor.TOP_LEFT)
MÉTODODrawable.to_edgeto_edge(direction: Direction, buff: float = 0.24) -> Self
Lleva el objeto al borde indicado del área segura, separado buff unidades.
Ejemplo
title = scene.text("Capítulo 2", role="title").to_edge(Direction.UP, buff=0.4)
MÉTODODrawable.to_cornerto_corner(corner: AnchorName | Anchor, buff: float = 0.24) -> Self
Lleva el objeto a una esquina del área segura (Anchor.TOP_LEFT, Anchor.BOTTOM_RIGHT… o su nombre, como "bottom_right"), separado buff unidades.
Ejemplo
page = scene.text("3 / 12", role="caption").to_corner(Anchor.BOTTOM_RIGHT, buff=0.3)

Anclajes y puertos

Puntos no dibujados que siguen al objeto en cada fotograma. Sirven como extremos de líneas, conectores, cotas y seguidores (ver Geometría).

MÉTODODrawable.anchor_pointanchor_point(anchor: Optional[AnchorName | Anchor] = None, *, offset: tuple[float, float] = (0.0, 0.0)) -> AnchorPoint
El desplazamiento local rota y escala con el objeto y con sus padres. Valores no finitos lanzan ValueError.
Parámetros
NombreTipoPredeterminadoDescripción
anchorAnchor | str | NoneNoneUno de los nueve anclajes de los límites locales, o su nombre ("top_left"); None equivale a Anchor.CENTER.
offsettuple[float, float](0.0, 0.0)Desplazamiento adicional en el espacio local.
Ejemplo
frame = scene.geometry.rect(2.25, 1.125)
corner = frame.anchor_point(Anchor.TOP_RIGHT, offset=(0.1, 0))
link = scene.geometry.line((-4, 2), corner)
MÉTODODrawable.with_portwith_port(name: str, anchor: AnchorName | Anchor, *, offset: tuple[float, float] = (0.0, 0.0)) -> Self
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.
Ejemplo
node = scene.geometry.rect(2, 1).with_port("out", Anchor.RIGHT, offset=(0.1, 0))
MÉTODODrawable.portport(name: str) -> AnchorPoint
Devuelve el AnchorPoint reactivo de un puerto definido con with_port. Un nombre desconocido lanza KeyError.
Ejemplo
target = scene.geometry.circle(0.5).move_to(4, 1)
edge = scene.geometry.connector(node.port("out"), target)
MÉTODODrawable.at_coordinateat_coordinate(coordinate: CoordinateRef) -> Drawable
Coloca el objeto en una coordenada simbólica de un espacio de coordenadas (plane.coord(x, y)). La posición sigue al espacio y a sus cambios de vista.
Ejemplo
plane = scene.viz.cartesian_2d(Axis.linear(-4, 4), Axis.linear(-2, 2))
peak = scene.geometry.dot(0.1).fill(GOLD).at_coordinate(plane.coord(1, 1.5))

Cada objeto expone también las expresiones lineales left, right, top, bottom, center_x, center_y, width y height para las restricciones de Layout.

Efectos y recortes

Resplandor, desenfoque, sombra, recorte por máscara y recorte del trazo. Los efectos se aplican a rellenos y trazos, incluidos los degradados.

MÉTODODrawable.glowglow(color: ColorLike, radius: float = 0.16, intensity: float = 1.0) -> Drawable
Añade un resplandor alrededor del objeto.
Parámetros
NombreTipoPredeterminadoDescripción
colorColorobligatorioColor del resplandor.
radiusfloat0.16Radio en unidades de escena.
intensityfloat1.0Intensidad relativa.
Ejemplo
from gaanim import BLUE, GOLD, Scene
scene = Scene(frame=(16, 9), background="#0f172a")
obj = scene.geometry.circle(0.56).fill(BLUE).stroke(GOLD, 0.04).move_to(0, 0)
obj.glow(GOLD, radius=0.225)
scene.play([obj.animate.grow_from_center().duration(0.8)])
scene.render()
animation preview
MÉTODODrawable.blurblur(sigma: float = 0.04) -> Drawable
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.
Ejemplo
blob = scene.geometry.circle(2).fill("#1E3A8A").blur(0.15)
MÉTODODrawable.shader_effectshader_effect(effect: Optional[PostProcess | Sequence[PostProcess]], *, margin: float = 0.25) -> Self
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
NombreTipoPredeterminadoDescripción
effectPostProcess | Sequence[PostProcess] | NoneobligatorioUn pase o una cadena de pases WGSL; None quita el efecto.
marginfloat0.25Unidades 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()
animation preview
MÉTODODrawable.mattematte(source: Optional[Drawable], mode: Literal["alpha", "alpha_inverted", "luma", "luma_inverted"] = "alpha") -> Self
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
NombreTipoPredeterminadoDescripción
sourceDrawable | NoneobligatorioEl mate: el objeto cuya forma o brillo deja ver a este; None quita el mate.
modestr"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 in zip(range(15), [GOLD, CORAL, "#22d3ee"] * 5)
])
stripes.matte(title)
scene.play([title.animate.write().duration(1.5)])
scene.render()
animation preview
MÉTODODrawable.glassglass(blur: float = 0.25, *, saturation: float = 1.4, refraction: float = 0.08, edge: float = 0.3, dispersion: float = 0.0, bevel: float = 0.12, transparency: float = 1.0, twist: float = 0.0) -> Self
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
NombreTipoPredeterminadoDescripción
blurfloat0.25Desenfoque de lo que hay detrás, en unidades de escena (la sigma de una gaussiana).
saturationfloat1.4Saturación de esos colores; 1 los deja igual.
refractionfloat0.08Cuánto se curva hacia dentro, en el borde, lo que hay justo fuera, en unidades de escena.
edgefloat0.3Brillo del borde, con la luz arriba a la izquierda, de 0 a 1.
dispersionfloat0.0Aberración cromática: cuánto se separan el rojo, el verde y el azul en el borde, de 0 a 1.
bevelfloat0.12Ancho del borde redondeado de la lente, en unidades de escena; hacia dentro el vidrio es plano y no deforma.
twistfloat0.0Desliza 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.
transparencyfloat1.0Cuá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 in enumerate([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()
animation preview
MÉTODODrawable.shadowshadow(color: ColorLike, x: float = 0.08, y: float = -0.08, blur: float = 0.06) -> Drawable
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.
Parámetros
NombreTipoPredeterminadoDescripción
colorColorobligatorioColor de la sombra; su alfa escala la opacidad.
x / yfloat0.08 / -0.08Desplazamiento en unidades de escena.
blurfloat0.06Desenfoque en unidades de escena.
Ejemplo
card = scene.geometry.rounded_rect(4, 2, 0.2).fill("#18202E").shadow("#00000080", x=0.12, y=-0.12, blur=0.1)
MÉTODODrawable.no_effectsno_effects() -> Drawable
Quita glow, blur y shadow sin tocar el relleno ni el trazo. Después del primer play o wait es un corte en el cursor: hasta ahí los efectos se ven.
MÉTODODrawable.tiptip(end: Optional[Literal["arrow", "dot"]] = "arrow", start: Optional[Literal["arrow", "dot"]] = None, *, length: Optional[float] = None, width: Optional[float] = None) -> Drawable
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
NombreTipoPredeterminadoDescripción
end / start"arrow" | "dot" | None"arrow" / NonePunta de cada extremo del camino.
lengthfloat | NoneNoneLargo de la punta de flecha; por defecto, cinco grosores de trazo y al menos 0.15.
widthfloat | NoneNoneAncho 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()
animation preview
MÉTODODrawable.blendblend(mode: BlendModeName = "normal") -> Drawable
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.
Parámetros
NombreTipoPredeterminadoDescripción
modestr"normal""normal", "multiply", "screen", "overlay", "darken", "lighten", "color_dodge", "color_burn", "hard_light", "soft_light", "difference", "exclusion", "hue", "saturation", "color", "luminosity" o "add".
Ejemplo
from gaanim import Scene
scene = Scene(frame=(16, 9), background="#101826")
panel = scene.geometry.rect(9, 4).fill("#2B6CB0").move_to(0, 0)
leak = scene.geometry.circle(1.6).fill("#F6AD55").move_to(-2.5, 0).blend("screen")
ink = scene.geometry.circle(1.6).fill("#F6AD55").move_to(2.5, 0).blend("multiply")
scene.play([leak.animate.move_to(-1, 0).duration(1.0), ink.animate.move_to(1, 0).duration(1.0)])
scene.render()
animation preview
MÉTODODrawable.echoecho(count: int = 5, *, delay: float = 0.04, decay: float = 0.6, hold: bool = False, start: Optional[float] = None, end: Optional[float] = None) -> Drawable
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
NombreTipoPredeterminadoDescripción
countint5Copias, de 1 a 32; 0 quita el eco.
delayfloat0.04Segundos entre copias; positivo.
decayfloat0.6Opacidad de cada copia respecto a la anterior, en (0, 1].
holdboolFalseCon 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 / endfloat | NoneNoneSegundos 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()
animation preview
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()
animation preview
MÉTODODrawable.countcount(count: float) -> Drawable
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
NombreTipoPredeterminadoDescripción
countfloatobligatorioCopias 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)
MÉTODODrawable.pointspoints(points: Sequence[tuple[float, float]]) -> Drawable
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
NombreTipoPredeterminadoDescripción
pointsSequence[tuple[float, float]]obligatorioUn punto por vértice, en las coordenadas en que se declaró la figura.
Ejemplo
tri = scene.geometry.polygon([(0, 0), (1, 0), (0, 1)]).points([(-1, -1), (1, -1), (0, 1)])
scene.play([tri.animate.points([(-2, -1), (2, -1), (0, 2)]).duration(1.0)])
MÉTODODrawable.squash_stretchsquash_stretch(amount: float = 0.1, max_ratio: float = 1.6) -> Drawable
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
NombreTipoPredeterminadoDescripción
amountfloat0.1Estiramiento por unidad de velocidad (unidades de escena por segundo); 0 quita el efecto.
max_ratiofloat1.6Estiramiento 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()
animation preview
MÉTODODrawable.stroke_profilestroke_profile(profile: Optional[Sequence[tuple[float, float]]]) -> Drawable
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
NombreTipoPredeterminadoDescripción
profileSequence[tuple[float, float]] | NoneobligatorioPares (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 in range(-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()
animation preview
MÉTODODrawable.stroke_taperstroke_taper(start: float = 0.2, end: float = 0.2) -> Drawable
Atajo de stroke_profile para pinceladas y flechas caligráficas.
Parámetros
NombreTipoPredeterminadoDescripción
start / endfloat0.2Fracció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()
animation preview
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
NombreTipoPredeterminadoDescripción
colorColorLike | NoneNoneColor del trazo; sin color se usa el trazo del tema.
widthfloat | NoneNoneGrosor del trazo; requiere color.
roughnessfloat1.0Escala del temblor: 0 dibuja geometría limpia y 1 el aspecto de rough-notation.
passesint2Veces que se dibuja la forma, de 1 a 8.
seedint0Semilla del garabato.
paddingPadding | NoneNoneCrecimiento 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.
Ejemplo
price = scene.text("99 €")
scene.play([price.annotate.crossed_off(color=RED, roughness=1.5, passes=1).animate.create()])
MÉTODOAnnotations.bracketbracket(sides: str | Sequence[str] = ("left", "right"), *, color: Optional[ColorLike] = None, width: Optional[float] = None, roughness: float = 1.0, passes: int = 2, seed: int = 0, padding: Optional[Padding] = None) -> Drawable
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
NombreTipoPredeterminadoDescripción
sidesstr | Sequence[str]("left", "right")Lados con corchete: "left", "right", "top" o "bottom".
Devuelve: Drawable — Los corchetes, ocultos hasta que un play los incluye.
Ejemplo
block = scene.text("primer paso\nsegundo paso")
scene.play([block.annotate.bracket("left", color=BLUE).animate.create()])
PROPIEDADDrawable.modifiersmodifiers: PathModifiers
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.
Ejemplo
from gaanim import BLUE, CORAL, GOLD, TEAL, WHITE, Scene
scene = Scene(frame=(16, 9))
star = scene.geometry.star(5, 1.1, 0.5).fill(GOLD).move_to(-5.0, 1.0)
zz = star.modifiers.zigzag(size=0.0, ridges=3)
star.modifiers.round_corners(0.04)
square = scene.geometry.square(1.6).fill(CORAL).move_to(-1.7, 1.0)
pb = square.modifiers.pucker_bloat(0.0)
hexagon = scene.geometry.regular_polygon(6, 1.0).fill(TEAL).move_to(1.7, 1.0)
tw = hexagon.modifiers.twist(0.0)
blob = scene.geometry.circle(0.9).fill(BLUE).move_to(5.0, 1.0)
blob.modifiers.wiggle_path(size=0.12, detail=3, frequency=1.5, seed=3)
ring = scene.geometry.circle(0.5).no_fill().stroke(WHITE, 0.04, align="center").move_to(0, -2.2)
rings = ring.modifiers.offset(0.15, join="round", copies=3)
scene.play([zz.animate.size(0.12), pb.animate.amount(-0.5), tw.animate.angle(1.4), rings.animate.amount(0.3)])
scene.play([pb.animate.amount(0.4).duration(0.8), tw.animate.angle(-1.0).duration(0.8)])
scene.render()
animation preview
MÉTODOPathModifiers.zigzagzigzag(size: float = 0.1, ridges: int = 4, *, smooth: bool = False) -> PathModifier
Los vértices quedan en su sitio, así que con size = 0 la forma no cambia.
Parámetros
NombreTipoPredeterminadoDescripción
sizefloat0.1Distancia de cada pico a cada lado del trazado, en unidades. Animable.
ridgesint4Picos por segmento, de 1 a 256.
smoothboolFalseOndas en lugar de esquinas.
Devuelve: PathModifier — El modificador, que anima size.
MÉTODOPathModifiers.round_cornersround_corners(radius: float) -> PathModifier
Redondea las esquinas entre dos tramos rectos; un lado más corto que dos radios limita sus esquinas y las curvas conservan sus vértices.
Parámetros
NombreTipoPredeterminadoDescripción
radiusfloatobligatorioRadio de cada esquina, >= 0. Animable.
Devuelve: PathModifier — El modificador, que anima radius.
MÉTODOPathModifiers.pucker_bloatpucker_bloat(amount: float) -> PathModifier
Los vértices se acercan al centro del trazado en esa fracción y las curvas entre ellos se alejan, o al revés con valores negativos.
Parámetros
NombreTipoPredeterminadoDescripción
amountfloatobligatorioEntre -1 (pucker, puntas) y 1 (bloat, lóbulos). Animable.
Devuelve: PathModifier — El modificador, que anima amount.
MÉTODOPathModifiers.twisttwist(angle: float) -> PathModifier
El giro se desvanece hasta cero en el vértice más lejano del centro.
Parámetros
NombreTipoPredeterminadoDescripción
anglefloatobligatorioGiro 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
NombreTipoPredeterminadoDescripción
sizefloat0.1Desplazamiento máximo a lo largo de la normal, en unidades. Animable.
detailint6Puntos por segmento, de 1 a 256.
frequencyfloat1.0Cambios por segundo. Animable.
seedint0Semilla del ruido.
Devuelve: PathModifier — El modificador, que anima size y frequency.
MÉTODOPathModifiers.offsetoffset(amount: float, *, join: Literal["miter", "round", "bevel"] = "miter", copies: int = 1) -> PathModifier
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
NombreTipoPredeterminadoDescripción
amountfloatobligatorioUnidades hacia fuera, o hacia dentro si es negativo. Animable.
join"miter" | "round" | "bevel""miter"Cómo gira el contorno en las esquinas.
copiesint1Contornos a amount, 2 * amount, …, de 1 a 64.
Devuelve: PathModifier — El modificador, que anima amount.
PROPIEDADPathModifier.animateanimate: PathModifierAnimation
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.
MÉTODODrawable.motion_blurmotion_blur(enabled: bool = True) -> Drawable
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.
Parámetros
NombreTipoPredeterminadoDescripción
enabledboolTrueFalse mantiene nítido el objeto y sus miembros.
MÉTODODrawable.post_processpost_process(enabled: bool = True) -> Drawable
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
NombreTipoPredeterminadoDescripción
enabledboolTrueFalse 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()
animation preview
MÉTODODrawable.trimtrim(start: Optional[float] = None, end: Optional[float] = None, offset: Optional[float] = None, mode: Optional[Literal["simultaneous", "sequential"]] = None) -> Self
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
NombreTipoPredeterminadoDescripción
start / endfloat | NoneNoneVentana visible del camino como fracción de su longitud; al principio valen 0 y 1.
offsetfloat | NoneNoneDesplaza la ventana; da la vuelta al final del camino.
modestr | NoneNone"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()
animation preview
MÉTODODrawable.clipclip(mask: Drawable, rule: Literal["nonzero", "evenodd"] = "nonzero", invert: bool = False) -> Drawable
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
NombreTipoPredeterminadoDescripción
maskDrawableobligatorioSilueta vectorial que recorta este objeto.
rulestr"nonzero"Regla de relleno de la máscara: "nonzero" o "evenodd".
invertboolFalseRecorta 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 % 2 else BLUE).move_to(-3 + 0.4 * i, 0)
    for i in range(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()
animation preview
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.
MÉTODODrawable.camera_viewcamera_view(frame: Optional[Drawable] = None, *, center: tuple[float, float] | Drawable | AnchorPoint | None = None, zoom: ScalarSource | None = None, fit: Literal["contain", "cover", "stretch"] = "contain", background: Paint | Literal["canvas"] | None = "canvas", exclude: Sequence[Drawable] = (), layers: Sequence[str] = ()) -> CameraView
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
NombreTipoPredeterminadoDescripción
frameDrawable | NoneNoneObjeto 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.
centertuple | Drawable | AnchorPoint | NoneNoneAdó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.
zoomfloat | Parameter | Computed | NoneNoneAumento 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.
fitstr"contain"Con un aumento dado por el marco: "contain" muestra el marco entero, "cover" llena la pantalla y "stretch" escala cada eje por separado.
backgroundPaint | 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.
excludeSequence[Drawable]()Objetos, con sus hijos, que la vista no muestra.
layersSequence[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 in range(40):
    scene.geometry.dot(0.04).fill(GOLD if i % 3 else 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()
animation preview
MÉTODODrawable.no_camera_viewno_camera_view() -> Drawable
Quita la vista de cámara desde el cursor: a partir de ahí la figura vuelve a dibujarse como una forma normal, y antes la vista se sigue viendo.
MÉTODODrawable.view_layerview_layer(name: Optional[str]) -> Drawable
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
NombreTipoPredeterminadoDescripción
namestr | NoneobligatorioNombre 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()
animation preview

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.
Ejemplo
scene.play([node.animate.move_to(3, 0).fill(GOLD).scale_to(1.5).duration(1.2)])

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.

MÉTODODrawable.followfollow(source: Endpoint, *, offset: tuple[float, float] = (0.0, 0.0), offset_space: Literal["world", "local"] = "world", delay: float = 0.0) -> Self
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
NombreTipoPredeterminadoDescripción
sourceEndpointobligatorioDrawable, AnchorPoint, PointRef o tupla.
offsettuple[float, float](0.0, 0.0)Desplazamiento respecto a la fuente.
offset_spacestr"world""world" mantiene el desplazamiento alineado con la pantalla; "local" lo rota y escala con la fuente.
delayfloat0.0Segundos 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()
animation preview

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 in range(5)]
for i, dot in enumerate(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()
animation preview
MÉTODODrawable.attach_toattach_to(source: Drawable) -> None
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()
animation preview
MÉTODODrawable.follow_tofollow_to(source: Drawable, offset: tuple[float, float]) -> None
Sigue el centro de source con un desplazamiento fijo offset. Devuelve None; para encadenar, usa follow.
Ejemplo
ball = scene.geometry.circle(0.3).fill(BLUE)
tag = scene.text("v", role="label")
tag.follow_to(ball, (0, 0.6))
scene.play([tag.animate.fade_in(), ball.animate.shift_by(3, 0)])
MÉTODODrawable.bind_x_from / bind_y_from / bind_position_frombind_x_from(source) · bind_y_from(source) · bind_position_from(source, axes="xy") -> None
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.
Ejemplo
point = scene.geometry.dot(0.1).fill(GOLD).move_to(-2, 1)
shadow = scene.geometry.dot(0.08).fill(GRAY).move_to(0, -2)
shadow.bind_x_from(point)
scene.play([shadow.animate.fade_in(), point.animate.shift_by(4, 0.5)])
MÉTODODrawable.bind_rotation_frombind_rotation_from(source: Drawable, *, ratio: float = 1.0, phase: float = 0.0) -> Self
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).
Ejemplo
driver = scene.mechanics.gear(0.69, 20).move_to(-0.69, 0)
driven = scene.mechanics.gear(0.41, 12).move_to(0.41, 0).bind_rotation_from(driver, ratio=-5/3)
scene.play([driven.animate.fade_in(), driver.animate.rotate_by(2.0)])
MÉTODODrawable.bind_translation_from_rotationbind_translation_from_rotation(source: Drawable, *, axis: Optional[Direction] = None, scale: float = 1.0) -> Self
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.
Ejemplo
pinion = scene.mechanics.gear(0.69, 20).move_to(0, 0.25)
rack = scene.mechanics.rack(2.75, 18).move_to(0, -0.81).bind_translation_from_rotation(
    pinion, axis=Direction.RIGHT, scale=0.69,
)
scene.play([rack.animate.fade_in(), pinion.animate.rotate_by(2.0)])
MÉTODODrawable.add_updateradd_updater(updater: Updater) -> None
Asocia un Updater nativo, por ejemplo Updater.orbit(cx, cy, radio, velocidad). Se evalúa en Rust y sigue siendo exacto al hacer seek.
Ejemplo
planet = scene.geometry.dot(0.12).fill(BLUE)
planet.add_updater(Updater.orbit(0, 0, 2, 1.0))
scene.wait(1)
MÉTODODrawable.remove_updaterremove_updater() -> None
Quita los updaters y las series muestreadas asociados al objeto desde el cursor.

Transformaciones 3D

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

MÉTODODrawable.move_to_3dmove_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Self
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.
Ejemplo
label = scene.text("origen").move_to_3d(0, 0, 0.5).billboard()
MÉTODODrawable.shift_by_3dshift_by_3d(dx: float, dy: float, dz: float) -> Self
Traslación relativa en tres ejes como corte inmediato.
MÉTODODrawable.scale_to_3dscale_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Self
Escala absoluta independiente en X, Y y Z. Acepta fuentes reactivas.
MÉTODODrawable.scale_by_3dscale_by_3d(x: float, y: float, z: float) -> Self
Multiplica la escala de cada eje en el cursor.
MÉTODODrawable.rotate_to_3drotate_to_3d(x: ScalarSource, y: ScalarSource, z: ScalarSource) -> Self
Rotación de Euler absoluta en radianes, en orden XYZ. Acepta fuentes reactivas.
Ejemplo
panel = scene.geometry.rect(2, 1).move_to_3d(0, 0, 0).rotate_to_3d(0.3, 0.6, 0)
MÉTODODrawable.rotate_by_3drotate_by_3d(axis: Literal["x", "y", "z"], radians: float) -> Self
Suma radians a la rotación alrededor del eje "x", "y" o "z".
MÉTODODrawable.with_pivot_3dwith_pivot_3d(x: float, y: float, z: float) -> Self
Fija el pivote 3D de rotación y escala.
MÉTODODrawable.billboardbillboard() -> Self
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)