0
# Animations
1
2
PyTermGUI's animation system provides smooth property transitions and dynamic effects for creating engaging user interfaces. The system supports value animations, attribute animations, and custom easing functions.
3
4
## Capabilities
5
6
### Animator
7
8
Central animation manager that schedules and executes animations with timing control and coordination.
9
10
```python { .api }
11
class Animator:
12
"""Animation management system."""
13
14
def __init__(self):
15
"""Initialize animator."""
16
17
def schedule(self, animation):
18
"""
19
Schedule animation for execution.
20
21
Parameters:
22
- animation: Animation instance to schedule
23
"""
24
25
def run(self):
26
"""Run animation loop until all animations complete."""
27
28
def stop(self):
29
"""Stop all animations."""
30
31
def update(self, delta_time: float):
32
"""Update all animations by time delta."""
33
34
@property
35
def is_running(self) -> bool:
36
"""Check if any animations are active."""
37
38
def clear(self):
39
"""Clear all scheduled animations."""
40
41
# Global animator instance
42
animator: Animator
43
```
44
45
### Float Animation
46
47
Numeric value animation with configurable easing and duration.
48
49
```python { .api }
50
class FloatAnimation:
51
"""Floating-point value animation."""
52
53
def __init__(self, duration: float, start: float, end: float,
54
easing: str = "linear"):
55
"""
56
Create float animation.
57
58
Parameters:
59
- duration (float): Animation duration in seconds
60
- start (float): Starting value
61
- end (float): Ending value
62
- easing (str): Easing function name
63
"""
64
65
@property
66
def value(self) -> float:
67
"""Get current animated value."""
68
69
@property
70
def progress(self) -> float:
71
"""Get animation progress (0.0 to 1.0)."""
72
73
@property
74
def is_finished(self) -> bool:
75
"""Check if animation is complete."""
76
77
def set_callback(self, callback: Callable[[float], None]):
78
"""Set callback function called with each value update."""
79
```
80
81
### Attribute Animation
82
83
Object attribute animation for animating widget properties.
84
85
```python { .api }
86
class AttrAnimation:
87
"""Object attribute animation."""
88
89
def __init__(self, obj: object, attr: str, duration: float,
90
end_value: float, easing: str = "linear"):
91
"""
92
Create attribute animation.
93
94
Parameters:
95
- obj: Target object to animate
96
- attr (str): Attribute name to animate
97
- duration (float): Animation duration in seconds
98
- end_value: Target value for attribute
99
- easing (str): Easing function name
100
"""
101
102
@property
103
def current_value(self) -> float:
104
"""Get current attribute value."""
105
106
@property
107
def is_finished(self) -> bool:
108
"""Check if animation is complete."""
109
```
110
111
### Animation Utilities
112
113
Helper functions for animation management and detection.
114
115
```python { .api }
116
def is_animated(target: object, attribute: str) -> bool:
117
"""
118
Check if object attribute is animated.
119
120
Parameters:
121
- target: Object to check
122
- attribute (str): Attribute name to check
123
124
Returns:
125
True if the specified attribute is animated
126
"""
127
```
128
129
### Easing Functions
130
131
Built-in easing functions for natural animation curves.
132
133
```python { .api }
134
# Available easing function names:
135
EASING_FUNCTIONS = [
136
"linear",
137
"ease_in",
138
"ease_out",
139
"ease_in_out",
140
"bounce_in",
141
"bounce_out",
142
"elastic_in",
143
"elastic_out"
144
]
145
```
146
147
## Usage Examples
148
149
### Basic Value Animation
150
151
```python
152
import pytermgui as ptg
153
import time
154
155
# Create a simple float animation
156
animation = ptg.FloatAnimation(
157
duration=2.0,
158
start=0.0,
159
end=100.0,
160
easing="ease_in_out"
161
)
162
163
# Set callback to handle value updates
164
def on_value_change(value):
165
print(f"Current value: {value:.2f}")
166
167
animation.set_callback(on_value_change)
168
169
# Schedule and run animation
170
ptg.animator.schedule(animation)
171
ptg.animator.run()
172
```
173
174
### Widget Property Animation
175
176
```python
177
import pytermgui as ptg
178
179
# Create widget and animate its width
180
container = ptg.Container(width=20, height=10)
181
182
# Animate width from 20 to 60 over 1.5 seconds
183
width_animation = ptg.AttrAnimation(
184
obj=container,
185
attr="width",
186
duration=1.5,
187
end_value=60,
188
easing="bounce_out"
189
)
190
191
ptg.animator.schedule(width_animation)
192
ptg.animator.run()
193
```
194
195
### Multiple Animations
196
197
```python
198
import pytermgui as ptg
199
200
# Create widget
201
window = ptg.Window("Animated Window", width=40, height=15)
202
203
# Create multiple animations
204
animations = [
205
ptg.AttrAnimation(window, "width", 2.0, 80, "ease_out"),
206
ptg.AttrAnimation(window, "height", 1.5, 25, "ease_in"),
207
]
208
209
# Schedule all animations
210
for animation in animations:
211
ptg.animator.schedule(animation)
212
213
# Run animations concurrently
214
ptg.animator.run()
215
```
216
217
### Color Animation
218
219
```python
220
import pytermgui as ptg
221
222
# Animate color transitions
223
class ColorAnimation:
224
def __init__(self, widget, duration, start_color, end_color):
225
self.widget = widget
226
self.start_rgb = start_color.rgb
227
self.end_rgb = end_color.rgb
228
229
# Create component animations
230
self.r_anim = ptg.FloatAnimation(duration, self.start_rgb[0], self.end_rgb[0])
231
self.g_anim = ptg.FloatAnimation(duration, self.start_rgb[1], self.end_rgb[1])
232
self.b_anim = ptg.FloatAnimation(duration, self.start_rgb[2], self.end_rgb[2])
233
234
# Set update callback
235
self.r_anim.set_callback(self.update_color)
236
237
def update_color(self, _):
238
r = int(self.r_anim.value)
239
g = int(self.g_anim.value)
240
b = int(self.b_anim.value)
241
new_color = ptg.RGBColor(r, g, b)
242
# Update widget color property
243
self.widget.styles.border = str(new_color)
244
245
# Usage
246
label = ptg.Label("Animated Text")
247
color_anim = ColorAnimation(
248
label,
249
duration=3.0,
250
start_color=ptg.Color("red"),
251
end_color=ptg.Color("blue")
252
)
253
254
ptg.animator.schedule(color_anim.r_anim)
255
ptg.animator.schedule(color_anim.g_anim)
256
ptg.animator.schedule(color_anim.b_anim)
257
ptg.animator.run()
258
```
259
260
### Chained Animations
261
262
```python
263
import pytermgui as ptg
264
265
def create_sequence():
266
"""Create sequence of chained animations."""
267
button = ptg.Button("Animated Button")
268
269
def phase1_done():
270
# Start second animation when first completes
271
phase2 = ptg.AttrAnimation(button, "width", 1.0, 20, "bounce_in")
272
phase2.set_callback(lambda _: print("Animation complete!"))
273
ptg.animator.schedule(phase2)
274
275
# First animation
276
phase1 = ptg.AttrAnimation(button, "height", 1.0, 5, "ease_out")
277
phase1.set_callback(lambda _: phase1_done() if phase1.is_finished else None)
278
279
ptg.animator.schedule(phase1)
280
return button
281
282
# Create and run sequence
283
animated_button = create_sequence()
284
ptg.animator.run()
285
```
286
287
### Animation in Window Manager
288
289
```python
290
import pytermgui as ptg
291
292
def animate_window_entrance(window):
293
"""Animate window appearing."""
294
# Start window small and grow it
295
window.width = 10
296
window.height = 5
297
298
# Animate to full size
299
width_anim = ptg.AttrAnimation(window, "width", 0.8, 60, "bounce_out")
300
height_anim = ptg.AttrAnimation(window, "height", 0.6, 20, "ease_out")
301
302
ptg.animator.schedule(width_anim)
303
ptg.animator.schedule(height_anim)
304
305
with ptg.WindowManager() as manager:
306
window = ptg.Window(
307
"[bold]Welcome!",
308
"",
309
ptg.Label("This window animated in"),
310
ptg.Button("Close", lambda btn: manager.stop()),
311
title="Animated Window"
312
)
313
314
manager.add(window)
315
animate_window_entrance(window)
316
317
# Run animations alongside window manager
318
import threading
319
animation_thread = threading.Thread(target=ptg.animator.run)
320
animation_thread.start()
321
```
322
323
### Custom Animation Callback
324
325
```python
326
import pytermgui as ptg
327
328
class PulsingLabel(ptg.Label):
329
"""Label that pulses with animation."""
330
331
def __init__(self, text, **attrs):
332
super().__init__(text, **attrs)
333
self.start_pulsing()
334
335
def start_pulsing(self):
336
"""Start pulsing animation."""
337
def pulse_callback(value):
338
# Use animation value to control text brightness
339
intensity = int(value)
340
self.value = f"[{intensity}]{self.original_text}[/{intensity}]"
341
342
self.original_text = self.value
343
344
# Create pulsing animation (back and forth)
345
pulse_out = ptg.FloatAnimation(1.0, 210, 240, "ease_in_out")
346
pulse_out.set_callback(pulse_callback)
347
348
def restart_animation():
349
if pulse_out.is_finished:
350
# Restart the pulse
351
new_pulse = ptg.FloatAnimation(1.0, 240, 210, "ease_in_out")
352
new_pulse.set_callback(pulse_callback)
353
ptg.animator.schedule(new_pulse)
354
355
pulse_out.set_callback(lambda v: (pulse_callback(v), restart_animation()))
356
ptg.animator.schedule(pulse_out)
357
358
# Usage
359
pulsing_label = PulsingLabel("This text pulses!")
360
ptg.animator.run()
361
```