Object state

Changing objects: animated state changes (.to()), instant writes (.set()), copies.

Contents:

  • k.Node: Objects are values: creating one does not put it in the scene (use s.add or a verb).
  • k.reparent: Moves an object to another group at the scheduled time, keeping its world position (inside a container, it takes its place in the flow).

Methods in this area:

  • obj.to: Animated state change: interpolates each prop from its value at the cursor to the target.
  • obj.set: Instant change at the cursor.
  • obj.unbind: Removes reactive bindings (all props when no name is given), keeping the current value.
  • obj.copy: Creates a new identity with the same props.

Back to the reference index.

k.Node (class)

k.Node(*, name: str | None = None, key: str | None = None, **props: object)

Objects are values: creating one does not put it in the scene (use s.add or a verb).

Documented together with obj.to.

Parameters:

Name Type Default Description
name str | None None
key str | None None
**props object variadic

Props (animatable with .to(), settable with .set() or in the constructor):

Prop Kind Default Interpolation
x float 0.0 linear
y float 0.0 linear
rotate float 0.0 linear
scale float 1.0 linear
scale_x float 1.0 linear
scale_y float 1.0 linear
anchor vec2 (0.0, 0.0) linear
opacity float 1.0 linear
z float 0.0 linear
visible bool True step_end

Layout-derived props (read-only, reactive, in the parent's coordinates): obj.width, obj.height, obj.left, obj.right, obj.top, obj.bottom, obj.center, obj.bbox, obj.position; obj.world.position and obj.world.center give global coordinates.

Members:

  • set: Instant change at the cursor.
  • to: Animated state change: interpolates each prop from its value at the cursor to the target.
  • unbind: Removes reactive bindings (all props when no name is given), keeping the current value.
  • edge: Point of the object's box named by an anchor ("right", "top-left", ...), in its parent's coordinates, reactive: k.Arrow(start=a.edge("right"), end=b.edge("left")).
  • age: Seconds since the object (or its nearest present ancestor) last entered the scene.
  • entered: Event at each entry of the object into the scene.
  • exited: Event at each exit of the object from the scene.
  • copy: Creates a new identity with the same props.
  • place: Declares where the object sits, relative to the frame (at="top", margin=) or to another object (above=, below=, left_of=, right_of=, inside= with pad=), with gap= (accepts a signal) and align=.
  • to_place: Animated change of placement: the .to of .place.
  • unpin: Releases the position constraint at the cursor: the object keeps its current position and is free to animate x/y.

k.Node.set (method)

obj.set(**props: Unpack[PropChanges]) -> Node

Instant change at the cursor. Passing a signal or a lambda creates a reactive binding from the cursor on (there are no updaters); obj.unbind("x") removes the binding.

Parameters:

Name Type Default Description
**props Unpack[PropChanges] variadic

Example:

@k.scene
def binding(s: k.Scene):
    leader = k.Dot(r=0.25, x=-4, y=1)
    follower = k.Dot(r=0.15, fill=k.RED)
    s.add(leader, follower)
    follower.set(x=leader.x, y=leader.y - 2)
    s.play(leader.to(x=4), duration=2)

See also: obj.to, obj.unbind, k.signal.

k.Node.to (method)

obj.to(
    *,
    duration: float | None = None,
    ease: EaseLike | None = None,
    delay: float = 0.0,
    blend: Blend = "replace",
    place: PlaceKeywords | Mapping[str, object] | None = None,
    unpin: bool = False,
    **props: Unpack[PropChanges],
) -> Animation

Animated state change: interpolates each prop from its value at the cursor to the target. Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)). Colors interpolate in OKLab.

Parameters:

Name Type Default Description
duration float | None None Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)).
ease EaseLike | None None Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)).
delay float 0.0 Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)).
blend Blend "replace" Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)).
place PlaceKeywords | Mapping[str, object] | None None
unpin bool False Accepts any public prop (x, y, scale, rotate, color, opacity...) plus duration=, ease=, delay=, blend="add", and unpin=True to release a .place constraint where the animation starts (to switch constraints instead, use obj.to_place(...)).
**props Unpack[PropChanges] variadic

Example:

@k.scene
def state(s: k.Scene):
    square = k.Square(1.5).place(at="center")
    s.play(k.draw(square))
    s.play(square.to(color=k.RED, rotate=45, scale=1.5), duration=1.5)
    s.wait(0.5)

See also: obj.set, anim.with_, s.during.

k.Node.unbind (method)

obj.unbind(*names: str)

Removes reactive bindings (all props when no name is given), keeping the current value. Required before animating a bound prop (error K0401).

Parameters:

Name Type Default Description
*names str variadic

Example:

@k.scene
def unbind(s: k.Scene):
    a = k.Dot(r=0.25, x=-3)
    b = k.Dot(r=0.25, x=-3, y=-1, fill=k.RED)
    s.add(a, b)
    b.set(x=a.x)
    s.play(a.to(x=3))
    b.unbind("x")
    s.play(b.to(x=-3))

See also: obj.set, obj.unpin.

k.Node.edge (method)

obj.edge(name: Anchor = "center") -> Expr[Vec]

Point of the object's box named by an anchor ("right", "top-left", ...), in its parent's coordinates, reactive: k.Arrow(start=a.edge("right"), end=b.edge("left")).

Parameters:

Name Type Default Description
name Anchor "center"

k.Node.age (property)

obj.age: Expr[float]  # read-only

Seconds since the object (or its nearest present ancestor) last entered the scene.

k.Node.entered (property)

obj.entered: EventSource[None]  # read-only

Event at each entry of the object into the scene.

k.Node.exited (property)

obj.exited: EventSource[None]  # read-only

Event at each exit of the object from the scene.

k.Node.copy (method)

obj.copy(frozen: bool = False) -> Node

Creates a new identity with the same props. By default the copy follows the original's reactive bindings; frozen=True copies only the values at the cursor. Use it to show the same visual in two places (an object has a single parent).

Parameters:

Name Type Default Description
frozen bool False By default the copy follows the original's reactive bindings; frozen=True copies only the values at the cursor.

Example:

@k.scene
def copy(s: k.Scene):
    original = k.Circle(r=0.8, fill=k.TEAL, fill_opacity=0.5).place(at="left", margin=3)
    s.play(k.draw(original))
    twin = original.copy(frozen=True).place(at="right", margin=3)
    s.play(k.fade_in(twin))

See also: k.Group, k.reparent.

k.Node.place (method)

obj.place(**kw: Unpack[PlaceKeywords]) -> Node

Written as: obj.place(at=, above=, below=, left_of=, right_of=, inside=, gap=, margin=, align=, pad=, clamp=False, weak=False)

Declares where the object sits, relative to the frame (at="top", margin=) or to another object (above=, below=, left_of=, right_of=, inside= with pad=), with gap= (accepts a signal) and align=. The relation keeps holding while the objects move. Returns the object itself, so it chains with the constructor.

Parameters:

Name Type Default Description
**kw Unpack[PlaceKeywords] variadic Keyword arguments (PlaceKeywords): at: Anchor | VecVal, above: Node, below: Node, left_of: Node, right_of: Node, inside: Node, gap: FloatVal, margin: FloatVal, pad: FloatVal, align: Align, clamp: bool, weak: bool, by: str.

Example:

@k.scene
def positions(s: k.Scene):
    box = k.Square(2).place(at="center")
    title = k.Text("Title").place(at="top", margin=0.6)
    label = k.Text("box", size=0.4).place(below=box, gap=0.3)
    s.add(box, title, label)
    s.play(box.to(scale=1.5))

See also: obj.to_place, obj.unpin, k.Row, obj.to.

k.Node.to_place (method)

obj.to_place(
    *,
    duration: float | None = None,
    ease: EaseLike | None = None,
    delay: float = 0.0,
    **place: Unpack[PlaceKeywords],
) -> Animation

Written as: obj.to_place(at=, above=, below=, left_of=, right_of=, inside=, gap=, margin=, align=, pad=, clamp=False, weak=False, duration=None, ease=None, delay=0.0)

Animated change of placement: the .to of .place. Takes the same keywords as .place(...) plus duration=, ease= and delay=, and moves the object from its current placement to the new one. The new constraint keeps holding afterwards.

Parameters:

Name Type Default Description
duration float | None None Takes the same keywords as .place(...) plus duration=, ease= and delay=, and moves the object from its current placement to the new one.
ease EaseLike | None None Takes the same keywords as .place(...) plus duration=, ease= and delay=, and moves the object from its current placement to the new one.
delay float 0.0 Takes the same keywords as .place(...) plus duration=, ease= and delay=, and moves the object from its current placement to the new one.
**place Unpack[PlaceKeywords] variadic Keyword arguments (PlaceKeywords): at: Anchor | VecVal, above: Node, below: Node, left_of: Node, right_of: Node, inside: Node, gap: FloatVal, margin: FloatVal, pad: FloatVal, align: Align, clamp: bool, weak: bool, by: str.

Example:

@k.scene
def replace(s: k.Scene):
    tri = k.Triangle().place(at="center")
    title = k.Text("title", size=0.5).place(above=tri, gap=0.4)
    s.add(tri, title)
    s.play(title.to_place(right_of=tri, gap=0.4))
    s.play(tri.to_place(at="left", margin=2))   # the title follows

See also: obj.place, obj.unpin, obj.to.

k.Node.unpin (method)

obj.unpin()

Releases the position constraint at the cursor: the object keeps its current position and is free to animate x/y. Inside an animation, obj.to(x=..., unpin=True) does the same where the animation starts. To switch constraints instead, use obj.to_place(...).

Example:

@k.scene
def release(s: k.Scene):
    tri = k.Triangle().place(at="center")
    title = k.Text("free").place(above=tri, gap=0.4)
    s.add(tri, title)
    s.play(title.to(x=3, unpin=True))
    title.unpin()  # the instant form, at the cursor

See also: obj.place, obj.to_place, obj.to.

k.reparent (function)

k.reparent(obj: Node, new_parent: Group) -> Animation

Moves an object to another group at the scheduled time, keeping its world position (inside a container, it takes its place in the flow). This is how you change parents: an object has exactly one (error K0103).

Parameters:

Name Type Default Description
obj Node required Instant move of obj into new_parent at the scheduled instant, keeping its world position (inside a container it takes its slot in the flow).
new_parent Group required Instant move of obj into new_parent at the scheduled instant, keeping its world position (inside a container it takes its slot in the flow).

Example:

@k.scene
def change_group(s: k.Scene):
    dot = k.Dot(r=0.25)
    left = k.Row(dot, k.Square(0.8), gap=0.3).place(at="left", margin=2)
    right = k.Row(k.Square(0.8), gap=0.3).place(at="right", margin=2)
    s.add(left, right)
    s.play(k.reparent(dot, right))
    s.wait(0.5)

See also: obj.copy, k.Group, k.Row.