JMathAnim DSL Quick Reference

Note:

  • All parameter keys are case-insensitive. style: accepts either a Map or a String (style name).
  • Parameters that expect coordinates admit both Coordinates objects (Vec, Point, etc.) or a list like [3,2].

Basics

shape(...)

Type Required params Optional params
circle segments
square
rectangle from:[x,y], to:[x,y]
triangle
polygon points:[[x,y],...]
polyline points:[[x,y],...]
segment from:[x,y], to:[x,y] numpoints
arc angle (radians) segments
regularPolygon sides
regularInscribedPolygon sides
annulus minRadius, maxRadius
logo commands (String)

Common params (all shapes): style, layer, visible, transform, stack, label

def s = shape(type: "circle", segments: 6,
              style: [color: "blue", thickness: 2],
              transform: [scale: 1.5, shift: [1, 0]])

def r = shape(type: "segment", from: [0,0], to: [1,1])
def p = shape(type: "polygon", points: [[0,0],[1,0],[0.5,1]])

Inline labels (label:): attach one or more labels to the shape, with the same options as the standalone label(...) DSL (t is an alias for location):

shape(type: "square", label: "x")                       // LaTeX label at t=0.5
shape(type: "square",
      label: [text: "x", t: 0.3, upside: true,
              style: [drawColor: "blue"], transform: [rotate: PI/2]])
shape(type: "square", label: [object: Shape.circle().scale(0.1), t: 0.3])
shape(type: "square", label: [[text: "A", t: 0], [text: "B", t: 0.5]]) // several
shape(type: "regularpolygon", sides: 3,                 // corner-anchored labels:
      label: [[text: "A", vertex: 0], [text: "B", vertex: 1], [text: "C", vertex: 2]])

vertex: n (alternative to t) anchors the label at path vertex #n, placed on the outward corner bisector — ideal for polygon vertices. Indices wrap circularly (-1 = last vertex) and the label is never rotated along the path.

Inline labels are internal objects of the shape: they update, draw and animate (fadeIn/fadeOut, etc.) together with it, and are never added to the scene on their own. Retrieve them with sq.getInternalObject("label0") ("label1", ...) or name them yourself with a key: entry:

def sq = shape(type: "square", label: [text: "x", key: "north"])
def lbl = sq.getInternalObject("north")

For a label managed independently of its path (added/removed from the scene by itself), use the standalone label(...) DSL instead.


point(...)

Key Type Default Description
at [x,y] / [x,y,z] / Coords [0,0] Position
style Map Style (e.g. dotStyle, color, thickness)
label String / Map / List Inline label(s), as in shape(...)
layer / visible / transform / stack Common props
addToScene boolean false Add to scene immediately
def p = point(at: [1, 0], style: [color: "blue", dotStyle: "cross", thickness: 4])
def a = point(at: [1, 0], label: "$A$")

stack: map

Exactly one of to, screen, or point must be present.

Key Type Description
to Boxable Destination object
screen String CENTER LEFT RIGHT UPPER LOWER UPPER_LEFT UPPER_RIGHT LOWER_LEFT LOWER_RIGHT
point [x,y] Fixed point destination
originAnchor String AnchorType of moving object
destinyAnchor String AnchorType of destination
gaps double / [h,v] Absolute gap
relativeGaps double / [h,v] Relative gap (mutually exclusive with gaps)
stack: [to: otherShape, originAnchor: "left", destinyAnchor: "right", gaps: 0.1]
stack: [screen: "upper_left"]
stack: [point: [1, 2], destinyAnchor: "center"]

AnchorType values (common reference)

CENTER LEFT RIGHT UPPER LOWER LEFT_AND_ALIGNED_UPPER LEFT_AND_ALIGNED_LOWER RIGHT_AND_ALIGNED_UPPER RIGHT_AND_ALIGNED_LOWER LOWER_AND_ALIGNED_LEFT LOWER_AND_ALIGNED_RIGHT UPPER_AND_ALIGNED_LEFT UPPER_AND_ALIGNED_RIGHT DIAG1 DIAG2 DIAG3 DIAG4 ZTOP ZBOTTOM

All keyword String values support prefix matching (case-insensitive). E.g. "cen" matches CENTER in AnchorType


transform: map

Key Type Description
scale double / [sx,sy] Uniform or non-uniform scale
shift [x,y] / Coords Translation
rotate double / [center, angle] Rotation (radians), optionally around a point
center true Center the object on screen
transform: [scale: 2, shift: [1, 0], rotate: 45*DEGREES]
transform: [rotate: [[0,0], PI/3]]   // rotate around [0,0]

Colors & Styles

style: map

Key Type Values / Notes
name String Named style template (loaded first)
color String Color name or hex
drawColor String Stroke color
fillColor String Fill color
thickness double Stroke width
thicknessTracksZoom boolean Camera zoom changes apparent thickness (default false)
thicknessTracksScale boolean Scaling the object scales its thickness (default true)
drawAlpha double Stroke opacity [0,1]
fillAlpha double Fill opacity [0,1]
visible boolean
layer int Rendering layer
lineCap String SQUARE ROUND BUTT
lineJoin String BEVEL ROUND MITER
strokeType String OUTSIDE INSIDE CENTERED
dotStyle String CIRCLE CROSS PLUS RING TRIANGLE_UP_HOLLOW TRIANGLE_UP_FILLED TRIANGLE_DOWN_FILLED TRIANGLE_DOWN_HOLLOW
dashStyle String SOLID DASHED DOTTED DASHDOTTED
style: [name: "myTemplate", color: "red", thickness: 2, dashStyle: "dashed"]
style: "myTemplate"   // shorthand: loads named style only

createStyle(...)

createStyle(name: "myStyle", style: [color: "red", thickness: 2])
Param Required Description
name yes Style name to register
style yes Map of style properties (same keys as style: map)

linearGradient(...)

Key Type Default Description
from [x,y] / Point [0,0] Start point
to [x,y] / Point [1,0] End point
relative boolean true Coords relative to shape
cycle String "no_cycle" no_cycle reflect repeat
0.0:, 0.5:, ... String / JMColor Color stops
def lg = linearGradient(from: [0,0], to: [1,0],
                        relative: true,
                        0.0: "blue", 0.5: "red", 1.0: "#00FF00")

radialGradient(...)

Key Type Default Description
center [x,y] / Point [0.5,0.5] Gradient center
radius double 0.5 Gradient radius
focusAngle double 0 Focus point angle (radians)
focusDistance double 0 Focus distance from center
relative boolean true Coords relative to shape
cycle String "no_cycle" no_cycle reflect repeat
0.0:, 1.0:, ... String / JMColor Color stops
def rg = radialGradient(center: [0.5,0.5], radius: 0.5,
                        0.0: "yellow", 1.0: "red")

colorScale(...)

def cs = colorScale(0.0: "blue", 0.5: "white", 1.0: "red")
def cs = colorScale((-2): "blue", 0: "white", 2: "red")  // negative keys: wrap in ()

Other Objects

axes(...)

Key Type Description
xRange / yRange [from, to] Primary tick range (or range: for both)
xStep / yStep double Primary tick step (default 1)
secondary Map Shorthand: sets both secondaryX and secondaryY
secondaryX / secondaryY Map {from,to,step,maxWidth} Secondary ticks
ticksX / ticksY List Individual ticks (Number or Map {at, label, type, maxWidth, scale})
style Map Global axes style
xStyle / yStyle Map Individual axis line style
xTickStyle / yTickStyle Map Tick mark style
xLegendStyle / yLegendStyle Map Tick label style

tick.type: PRIMARY (default) or SECONDARY

def ax = axes(xRange: [-3, 3], yRange: [-2, 2], xStep: 1, yStep: 1,
              secondaryX: [step: 0.5],
              ticksX: [[at: Math.PI, label: r"\pi"]])

grid(...)

Cartesian grid. Added to the scene by default (add: false to opt out).

Key Type Default Description
center [x,y] / Coords [0,0] Grid center
steps double / [sx,sy] [1,1] Primary grid step
divisions int / [dx,dy] [1,1] Secondary subdivisions
primaryStyle Map Style for primary lines
secondaryStyle Map Style for secondary lines
def g = grid(steps: 1, divisions: 4,
             primaryStyle: [color: "gray"],
             secondaryStyle: [color: "lightgray"])

polarGrid(...)

Polar grid. Added to the scene by default (add: false to opt out).

Key Type Default Description
center [x,y] / Coords [0,0] Grid center
radiusStep double 1 Distance between primary circles
angularDivisions int 6 Primary radial rays over the full circle
divisions int / [dr,da] [1,1] Secondary radial / angular subdivisions
primaryStyle Map Style for primary lines
secondaryStyle Map Style for secondary lines
def pg = polarGrid(radiusStep: 1, angularDivisions: 12, divisions: [2, 2])

funcGraph(...)

Key Type Default Description
func Closure / DoubleUnaryOperator / DoubleBinaryOperator required The function to plot
xRange (range) [from, to] Domain; if omitted the graph is dynamic (follows the camera)
numPoints int Sample points (only with an explicit range)
dynamic boolean Force dynamic range even with xRange
style / label Style and inline label(s)
def fg = funcGraph(func: { x -> Math.sin(x) }, xRange: [-3, 3], style: [color: "blue"])
def fg2 = funcGraph(func: Math.&cos)   // dynamic: follows the camera view

parametricCurve(...)

Key Type Description
x, y Closure / operator / number Cartesian components (z optional)
r, theta Closure / operator / number Polar components (switches to polar mode)
trange (range) [tmin, tmax] required parameter domain
numPoints int Sample points
coordinates String cartesian (default) or polar
tpoints Number / List Extra parameter values to force as nodes
style / label Style and inline label(s)
def c = parametricCurve(x: { t -> Math.cos(t) }, y: { t -> Math.sin(t) }, trange: [0, 2*PI])
def rose = parametricCurve(r: { t -> Math.cos(3*t) }, theta: { t -> t }, trange: [0, PI])

contourPlot(...)

Key Type Description
function BiFunction (x,y) -> value required
levels List or Map {min,max,step} Contour levels required
xMin/xMax/yMin/yMax double Domain (default: camera view)
cols / rows int Grid resolution (default 100)
colorScale ColorScale Color scale instance
style Map Applied to all contour shapes
def cp = contourPlot(
    function: (x, y) -> x*x + y*y,
    levels: [min: 0.5, max: 3.0, step: 0.5],
    cols: 150, rows: 150,
    colorScale: colorScale(0.0: "blue", 1.0: "red"))

densityPlot(...)

Pixel heat-map of a scalar field. Added to the scene by default (add: false to opt out).

Key Type Default Description
function Closure (x,y) or (x,y,t) / operator required Scalar field (t is animatable)
range [xmin,ymin,xmax,ymax] / number / preset camera view Domain (unit centered screen trig trigCentered)
coordinates String cartesian cartesian or polar (field gets r, theta)
colorScale ColorScale viridis Color scale
parallel boolean true Parallel row evaluation
style Map Mainly for opacity (alpha)
def dp = densityPlot(function: { x, y -> Math.sin(x) * Math.cos(y) }, range: "centered")

vectorField(...)

Grid of arrows sampling a planar field. Added to the scene by default.

Key Type Default Description
function Closure (x,y)/(x,y,t)Vec or [vx,vy] required The field (t animatable)
range [xmin,ymin,xmax,ymax] / number / preset camera view Domain
cols / rows int 15 Grid resolution
arrows String simple simple (stroke-only) or classic (filled head)
fill boolean Filled arrows (default: true for classic)
normalize boolean false Same length for every arrow (direction only)
scaleFactor double 0.9 Fraction of a cell for the longest arrow
lengthScale double Fixed world length per unit magnitude (disables auto-scale)
autoScale boolean true Auto-scale longest arrow to a cell
colorScale ColorScale Color arrows by magnitude
colorByMagnitude boolean true Auto viridis coloring by magnitude
parallel boolean true Parallel row evaluation
style Map Applied to every arrow
def vf = vectorField(function: { x, y -> Vec.to(-y, x) },
                     range: [-3, -3, 3, 3], cols: 20, rows: 20, arrows: "classic")

arrow(...)

Key Type Default Description
from [x,y] / Coords required Start point
to [x,y] / Coords required End point
head int / String ARROW1 End arrowhead
tail int / String NONE_BUTT Start arrowhead
curvature double Arrow curvature
arrowThickness double Arrowhead thickness
startScale / endScale double Arrowhead scale
label String / Map Text label
lengthLabel String / Map Length label
vecLabel String / Map Vector label
style Map Style

Arrow types: NONE_BUTT(0) ARROW1(1) ARROW2(2) ARROW3(3) SQUARE(4) BULLET(5)

def ar = arrow(from: [0,0], to: [1,1], head: "ARROW2", tail: "NONE_BUTT",
               label: [text: r"v", scale: 0.8, gap: 0.05])

Label sub-map keys: text, format, t (location 0–1), color, drawColor, fillColor, thickness, scale, gap, upside, anchor, rotation (FIXED ROTATE SMART), style (sub-map), transform (sub-map)


connector(...)

Same params as arrow(...) plus:

Key Type Description
from MathObject required — source object
to MathObject required — destination object
connectionType String Exit strategy — auto (default), fixed, boxed, circular, inscribed, ellipse, center. Works for stepped too (e.g. center routes between the object centers). Must be set (not auto) for the scale params below to apply
startScaleBBox double Multiplicative bbox start scale (default 1; grows with the object; ignored when connectionType is auto or center)
endScaleBBox double Multiplicative bbox end scale (default 1; ignored when connectionType is auto or center)
gaps number / [h,v] Fixed clearance added to each object's bbox before computing the exit — a constant distance (unlike the scale). Works with any connectionType, incl. center (then exits a fixed distance from the center)
def con = connector(from: shapeA, to: shapeB, head: 2,
                    curvature: 0.3, label: "f")

delimiter(...)

Standard form:

Key Type Default Description
from [x,y] / Coords required Start point
to [x,y] / Coords required End point
type String BRACE BRACE PARENTHESIS BRACKET INVISIBLE LENGTH_ARROW LENGTH_BRACKET
gap double 0.1 Distance from anchor to delimiter body

Stacked form:

Key Type Description
stackedTo MathObject required — object to stack to
anchor String UPPER(def) LOWER LEFT RIGHT
type String See above
gap double Distance from object

Common optional params:

Key Description
delimiterScale Scale of the delimiter shape
amplitudeScale Scale of the delimiter amplitude
labelGap Distance from label to delimiter shape
label String, Map {text, color, scale, gap, rotation, style, transform} or [object: mathObject]
lengthLabel String or Map {format, color, scale, gap, rotation, style, transform}
rotation FIXED ROTATE SMART
style Style map
def d = delimiter(from: [0,0], to: [2,0], type: "BRACE", gap: 0.15,
                  label: [text: r"$L$", scale: 0.8, gap: 0.05])

def d = delimiter(stackedTo: myShape, anchor: "UPPER", type: "BRACKET",
                  lengthLabel: [format: "0.00", color: "blue"])

label(...)

Attaches a tippable object to a path. Exactly one mode is required: text (a LabelTip), type (an arrowhead / equal-mark TippableObject), or object (any MathObject as the tip).

Key Type Default Description
path Pathable required Path object to attach to
text String Mode: LaTeX label text
type String Mode: arrow1arrow3, square, bullet, or equal1equal4
object MathObject Mode: arbitrary object as the tip
location (t) double 0.5* Position along path [0,1] (*path-dependent default)
upside boolean Place above path
gap double Distance to shape
gapRelative boolean true Gap relative to size
rotation String FIXED ROTATE SMART
slopeDirection String / boolean POSITIVE NEGATIVE
anchor AnchorType
scale double / [sx,sy] Scale the tip
rotate double Rotate the tip (radians)
style Map / String Style properties
def lt = label(path: myShape, location: 0.5, text: r"$A$",
               upside: true, gap: 0.1, rotation: "rotate")
def ah = label(path: seg, type: "arrow2", t: 1)
def em = label(path: seg, type: "equal2")   // equal-length marks

delimiter(...) accepts a nested labelTip(...) block for its own label; that is a different, delimiter-scoped helper, not this top-level command.


Text & LaTeX

latex(...)

Key Type Description
text String required — LaTeX expression
anchor String Anchor side used to position the object
style Map / String Style properties or named style
latexStyle LatexStyle / String Per-glyph coloring style (see latexStyle(...)) or a registered name
colorToIndices String / List Per-glyph coloring by index (see below)
layer / visible / transform Common props
def eq = latex(text: r"$e^{i\pi}+1=0$")
def q  = latex(text: "$x^2+y^2$", colorToIndices: [["blue", 0, 1], ["red", 3, 4]])

colorToIndices forms: "blue" (all glyphs), ["blue", 1, 2] (glyphs 1 & 2), [["blue", 1, 2], ["red", 3, 5]] (several groups); indices accept ranges like 0..5.


text(...)

Plain (non-LaTeX) text.

Key Type Default Description
text String required The text to display
font String Font family, e.g. "Serif"
fontSize (height, size) double 0.5 Text height in math units
bold / italic / outline boolean Font flags
style Map / String Style properties
def t = text(text: "Hello", font: "Serif", fontSize: 0.8, style: [color: "blue"])

latexStyle(...)

Declaratively colors the glyphs of a LaTeX formula with ordered rules (later rules override earlier ones). See the Coloring Formulas chapter for the full token model.

Key Type Description
rules List of Maps required — coloring rules (see below)
apply LatexMathObject / List Apply the built style to these formula(s)
name String Register the style under this name for reuse

Each rule has a paint part (color for both draw and fill, drawColor / fillColor for each one separately, or a full style map/name) and optional conditions: char (exact CHAR), match / differ (token spec on the glyph), prev / next (neighbour token specs). A token spec is a String (its LaTeX name) or a Map (type, string, subscript, depth, ...).

latexStyle(apply: formula, name: "rowColMatrix", rules: [
    [char: "X", color: "steelblue"],
    [match: [subscript: true], color: "gold"],
])

apply(...)

Applies styling and common props to one or many existing objects.

Key Type Description
obj object / List / array required — target(s)
style Map / String Style properties
transform Map scale, shift, rotate
layer / visible / stack Common props
apply(obj: [a, b, c], style: [drawColor: "blue"], transform: [rotate: PI/2])

Layouts

layout(...)

Builds a GroupLayout (usable with .setLayout(...) or the animSetLayout DSL). Selected by type (default simple). Common param gaps accepts a number or [h, v].

type Required Optional
simple layout (LayoutType name) refPoint
box rowSize corner, direction (BoxDirection)
flow width, corner direction
circular center, radius clockwise, rotation, initialAngle
spiral orientation (SpiralOrientation), center, spiralGap
heap base
pascal refPoint
path path rotation, parametric
random deviation distribution (normal/uniform), center
destiny destinyGroup

LayoutType names: center right left upper lower uright uleft dright dleft rupper lupper rlower llower diag1diag4.

def lay = layout(type: "circular", center: [0, 0], radius: 3)
def box = layout(type: "box", rowSize: 3, gaps: [0.1, 0.1], corner: [0, 0])

Constructible Objects

Points

Method Required Optional
ctPoint(at:[x,y]) at style, layer, visible, transform, name
ctMidPoint(A:, B:) a, b
ctMidPoint(segment:) segment (CTSegment)
ctIntersectionPoint(A:, B:) a, b index (0/1)
ctMirrorPoint(point:, axis:) point, axis (CTAbstractLine)
ctMirrorPoint(point:, A:, B:) point, a, b
ctMirrorPoint(point:, center:) point, center
ctRotatedPoint(point:, center:, angle:) point, center, angle
ctTranslatedPoint(point:, vector:) point, vector (CTVector)
ctPointOnObject(on:) on (PointOwner)

All CT methods accept: style, layer, visible, transform, name (CT name)

def A = ctPoint(at: [0, 0])
def M = ctMidPoint(A: A, B: B)
def I = ctIntersectionPoint(A: line1, B: circle1, index: 0)
def R = ctRotatedPoint(point: A, center: O, angle: Math.PI/3)

Lines

Method Forms
ctLine A:, B: or A:, dir: (HasDirection)
ctSegment A:, B:
ctRay A:, B: or A:, dir:
ctVector A:, B:
ctAngleBisector A:, B: (vertex), C:
ctPerpBisector A:, B: or segment: (CTSegment)
ctLineOrthogonal A:, B: or A:, dir:
ctTransformedLine(line:, ...) mirrorAxis: / mirrorCenter: / vector: / center:+angle:
def l  = ctLine(A: A, B: B)
def s  = ctSegment(A: A, B: B, style: [color: "blue"])
def pb = ctPerpBisector(segment: s)
def tl = ctTransformedLine(line: l, mirrorAxis: l2)
def tl = ctTransformedLine(line: l, center: O, angle: Math.PI/4)

Circles

Method Forms
ctCircle center:+radius: / center:+through: / A:+B:+C:
ctCircleArc center:, A:, B:
ctCircleSector center:, A:, B:
ctSemiCircle A:, B:
ctEllipse focus1:, focus2:, A:
ctTransformedCircle(circle:, ...) mirrorAxis: / mirrorCenter: / vector: / center:+angle:
def c  = ctCircle(center: O, radius: 1.5)
def c  = ctCircle(A: P, B: [1,1], C: Q) //Circle through P, (1,1) and Q
def e  = ctEllipse(focus1: F1, focus2: F2, A: P) //Ellipse with focus F1, F2 that passes through P
def tc = ctTransformedCircle(circle: c, vector: v)

ctLatex(...)

Param Type Default Description
text String required LaTeX expression
anchor [x,y] / Coords required Anchor point
anchorType String "DIAG4" Anchor side (see AnchorType)
gap double 0.3 Gap from anchor
scale double 0.5 Size scale
style Map Style properties
def lbl = ctLatex(text: r"\alpha", anchor: [1, 0],
                  anchorType: "left", gap: 0.15, scale: 0.7)

Other constructibles

Method Forms
ctPolygon points:[A,B,C,...] (free) or A:+B:+sides: (regular)
ctAngleMark center:, A:, B: + optional radius:, isRight:
ctTangent point:+circle: + optional index: or circle1:+circle2: + optional index:
def poly = ctPolygon(points: [A, B, C, D])
def hex  = ctPolygon(A: A, B: B, sides: 6)
def am   = ctAngleMark(center: O, A: P1, B: P2, radius: 0.15, isRight: true)
def t    = ctTangent(point: P, circle: c, index: 0)
def t    = ctTangent(circle1: c1, circle2: c2, index: 2)

Animations

Every anim* command runs immediately unless run: false is given, and always returns the created Animation (useful for composing with animGroup / animJoin).

Common params (most anim commands):

Key Type Description
obj MathObject / List Object(s) to animate
runtime double Duration in seconds (default 1)
run boolean Play now (default true); false just builds it
effects Map Extra effects (see below); shift/rotate/scale/affine and the position anims
lambda String / Closure Timing function (see below)

effects: map

Key Type Description
turns int Number of extra rotations
scale double Scale bump amplitude
alpha double Alpha (transparency) bump
jump double Jump height
jumptype String PARABOLICAL(def) SEMICIRCLE ELLIPTICAL TRIANGULAR FOLIUM SINUSOIDAL SINUSOIDAL2 CRANE BOUNCE1 BOUNCE2
animShift(obj: sq, dx: 1, effects: [jump: 1, jumptype: "crane", turns: 1])

lambda: timing

A String names a parameterless UsefulLambdas function (prefix-matching): smooth(def) backAndForth backAndForthLinear backAndForthBounce1 backAndForthBounce2 bounce1 bounce2 reverse. A Closure gives a custom timing, e.g. lambda: { t -> t * t }. For parameterized lambdas pass the operator directly, e.g. lambda: restrictTo(0.25, 0.5).


animShift(...) / animRotate(...) / animScale(...)

Command Required Optional
animShift obj + (vector or dx/dy/dz)
animRotate obj + (angle rad or degrees) center
animScale obj + (scale or sx/sy/sz) center

center accepts a point/Vec or [x,y]; if omitted the object uses its own center. scale is a single number (uniform) or [sx,sy].

animShift(obj: sq, dx: 1, dy: 0.5)
animRotate(obj: sq, degrees: 90, center: [0, 0], runtime: 2)
animScale(obj: sq, scale: 0.5, effects: [turns: 1])

animCamera(...)

type Required Description
shift vector or dx/dy Pan the view
scale scale or zoom scale > 1 zooms out; zoom: 5 == scale: 0.2
zoomToRect rect Rect, [xmin,ymin,xmax,ymax], a number n (square [-n,n]) or a preset
zoomToObjects obj Fit the given object(s)
zoomToAllObjects Fit all objects in the scene

Optional camera: selects the Camera (default: scene camera).

animCamera(type: "shift", dx: 1, dy: -1, runtime: 4)
animCamera(type: "scale", zoom: 5)
animCamera(type: "zoomToRect", rect: [-1, -1, 1, 1])

animAffine(...)

Points accept a point/Vec or [x,y].

type Params
similarity origin/destiny: 2 points each, or two Rect
inverseSimilarity origin/destiny: 2 points each
reflection origin, destiny (single points)
reflectionByAxis axis: 2 points
affine origin/destiny: 3 points each
animAffine(type: "affine", obj: grid, origin: [A, B, C], destiny: [D, E, F])
animAffine(type: "reflection", obj: sq, origin: [1, 0], destiny: [-1, 0])
animAffine(type: "similarity", obj: tri, origin: [A, B], destiny: [C, D])

animMoveAlongPath(...)

Key Type Default Description
obj MathObject required Single object to move
path Pathable required Path to follow (Shape, JMPath, function graph...)
anchor String center Point of the object on the path
rotation String fixed fixed rotate (follow tangent) smart (never upside down)
parametrized boolean true true arc-length (constant speed); false Bézier
rotationSmoothing double 0.01 Corner smoothing half-window; 0 = abrupt turns
animMoveAlongPath(obj: dot, path: circle)
animMoveAlongPath(obj: arrow, path: curve, rotation: "rotate", runtime: 3)

animStackTo(...) / animAlign(...) / animSetLayout(...)

Command Required Optional
animStackTo obj, dst anchor (def center), gap
animAlign obj, dst, type (left/right/upper/lower/hcenter/vcenter)
animSetLayout obj (group/List), layout corner, gap

dst accepts a MathObject, Rect, point/Vec or [x,y]. layout is a LayoutType name (right, upper, diag1...), a GroupLayout (from the layout(...) DSL), or a spec map [type: "circular", center: [0,0], radius: 2].

animStackTo(obj: sq, dst: circle, anchor: "right", gap: 0.1)
animAlign(obj: sq, dst: circle, type: "left")
animSetLayout(obj: g, layout: "right", gap: 0.1)

animGroup(...) / animJoin(...)

Build the children with run: false, then combine them:

Command Required Optional Timing
animGroup anims delay (0–1 stagger), effects, lambda Plays together; total = max child runtime (no runtime)
animJoin anims runtime, lambda Plays in sequence; default total = sum of children, default lambda linear
def a1 = animShift(obj: s1, dx: 1, run: false)
def a2 = animRotate(obj: s2, degrees: 90, run: false)

animGroup(anims: [a1, a2], delay: 0.5)
animJoin(anims: [a1, a2], runtime: 3)

appear(...) / disappear(...)

Bring objects into / out of the scene. obj is a single object or a List.

Command type (default) Type-specific params
appear showcreation* (fadein, growin, movein) growin: angle, orientation; movein: enter (edge)
disappear fadeout* (shrinkout, moveout) shrinkout: angle, orientation; moveout: exit (edge)

*showcreation aliases: draw, sketch. orientation: horizontal vertical both. Edge values: left right upper lower upper_left upper_right lower_left lower_right center.

appear(obj: s, type: "growin", angle: PI, orientation: "horizontal")
disappear(obj: [s1, s2], type: "moveout", exit: "right")

morph(...)

Morphs one object into another (removes from, adds to).

Key Type Description
from / to MathObject required — initial / final object
type String auto(def) flip twist
orientation String flip: horizontal vertical both
pivotal int twist: pivotal segment index (both must be Shape)
morph(from: square, to: circle)
morph(from: a, to: b, type: "flip", orientation: "horizontal")

highlight(...)

Momentarily draws attention to objects without permanent changes.

type Params
highlight (def) scale (def 1.5)
twist scale, angle (def 15°)
contour box (bbox instead of outline), gap, color, thickness, amplitude
boxHighlight
highlight(obj: s, scale: 2)
highlight(obj: text, type: "contour", box: true, gap: 0.1, color: "yellow", thickness: 12)

animScalar(...)

Animates the scalar value of Parametric object(s) (e.g. the t of a density/vector field) from from to to.

Key Type Default Description
obj Parametric / List required Scalar object(s)
from double 0 Initial value
to double required Final value
runtime / run / lambda Common anim params
animScalar(obj: t, from: 0, to: 2*PI, runtime: 3)

mathTransform(...)

Morphs a LaTeX formula into another, mapping/removing/adding individual glyphs, optionally over sequential stages.

Key Type Description
from / to String / LatexMathObject required — initial / final formula
maps List Glyph mappings: [orig, dst] pairs, or [orig:.., dst:.., stage:.., style:.., asGroup:.., lambda:.., effects:..]
removes / adds List Ints/lists of indices, or maps [indices:.., style:.., stage:.., effects:..]
align [toIndex, fromIndex] Align to glyph over a from glyph
defaultRemove / defaultAdd String Default styles (shrink_out / grow_in)
defaultRemoveStage / defaultAddStage int Default stages (1)
delay double Stagger sub-animations within each stage (0,1)
runtime / run / lambda Common anim params

Map style: interpolation flip_horizontally flip_vertically flip_both. effects on maps: [turns, scale, alpha, jump, jumptype]; on removes/adds only turns.

mathTransform(
    from: r"$aX b$", to: r"$Z$", runtime: 3,
    removes: [[indices: 0, style: "moveout_left", stage: 1]],
    maps:    [[orig: 1, dst: 0, stage: 2]])