CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-brython

Python-to-JavaScript transpiler that enables Python 3 development in web browsers with full DOM integration and standard library support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

timers-animation.mddocs/

Timers and Animation

Timer functions and animation frame requests for time-based functionality and smooth animations in web applications. Provides Python interfaces to browser timing APIs.

Capabilities

Basic Timers

Execute functions after delays or at regular intervals.

def set_timeout(func: Callable, interval: int, *args) -> int:
    """
    Execute function after specified delay.
    
    Args:
        func: Function to execute
        interval: Delay in milliseconds
        *args: Arguments to pass to function
        
    Returns:
        Timer ID for cancellation
    """

def set_interval(func: Callable, interval: int, *args) -> int:
    """
    Execute function repeatedly at specified interval.
    
    Args:
        func: Function to execute
        interval: Interval in milliseconds
        *args: Arguments to pass to function
        
    Returns:
        Timer ID for cancellation
    """

def clear_timeout(timer_id: int) -> None:
    """
    Cancel scheduled timeout.
    
    Args:
        timer_id: Timer ID returned by set_timeout
    """

def clear_interval(timer_id: int) -> None:
    """
    Cancel repeating interval.
    
    Args:
        timer_id: Timer ID returned by set_interval
    """

Usage:

from browser.timer import set_timeout, set_interval, clear_timeout, clear_interval

def delayed_message():
    print("This message appears after 2 seconds")

def periodic_update():
    print("Updating every 5 seconds...")

# Schedule one-time execution
timeout_id = set_timeout(delayed_message, 2000)

# Schedule repeating execution  
interval_id = set_interval(periodic_update, 5000)

# Cancel timers if needed
def cancel_timers():
    clear_timeout(timeout_id)
    clear_interval(interval_id)
    print("All timers cancelled")

# Cancel after 30 seconds
set_timeout(cancel_timers, 30000)

Animation Frames

Smooth animations synchronized with browser refresh rate.

def request_animation_frame(func: Callable) -> int:
    """
    Request function execution on next animation frame.
    
    Args:
        func: Animation function to execute
        
    Returns:
        Animation frame ID for cancellation
        
    The callback function receives timestamp as parameter.
    """

def cancel_animation_frame(frame_id: int) -> None:
    """
    Cancel pending animation frame request.
    
    Args:
        frame_id: Frame ID returned by request_animation_frame
    """

Usage:

from browser.timer import request_animation_frame, cancel_animation_frame
from browser import document
from browser.html import DIV

# Create animated element
animated_div = DIV("Animated Content", style={
    'position': 'absolute',
    'left': '0px',
    'top': '100px',
    'width': '100px',
    'height': '100px',
    'background': 'blue',
    'color': 'white',
    'text-align': 'center'
})

document.body <= animated_div

# Animation state
animation_state = {
    'x': 0,
    'direction': 1,
    'running': False,
    'frame_id': None
}

def animate_element(timestamp):
    """Animation loop function."""
    if not animation_state['running']:
        return
    
    # Update position
    animation_state['x'] += animation_state['direction'] * 2
    
    # Reverse direction at boundaries
    if animation_state['x'] >= 500 or animation_state['x'] <= 0:
        animation_state['direction'] *= -1
    
    # Apply position
    animated_div.style.left = f"{animation_state['x']}px"
    
    # Continue animation
    animation_state['frame_id'] = request_animation_frame(animate_element)

def start_animation():
    """Start the animation."""
    if not animation_state['running']:
        animation_state['running'] = True
        animation_state['frame_id'] = request_animation_frame(animate_element)

def stop_animation():
    """Stop the animation."""
    animation_state['running'] = False
    if animation_state['frame_id']:
        cancel_animation_frame(animation_state['frame_id'])
        animation_state['frame_id'] = None

# Control buttons
from browser.html import BUTTON
from browser import bind

start_btn = BUTTON("Start Animation")
stop_btn = BUTTON("Stop Animation")

@bind(start_btn, 'click')
def handle_start(event):
    start_animation()

@bind(stop_btn, 'click') 
def handle_stop(event):
    stop_animation()

document.body <= start_btn
document.body <= stop_btn

Performance Timing

Monitor and optimize timing performance.

def set_loop_timeout(seconds: int) -> None:
    """
    Set maximum execution time for loops to prevent blocking.
    
    Args:
        seconds: Maximum execution time in seconds
    """

def get_timestamp() -> float:
    """
    Get high-resolution timestamp.
    
    Returns:
        Timestamp in milliseconds with microsecond precision
    """

Usage:

from browser.timer import set_loop_timeout, get_timestamp

# Set timeout for long-running operations
set_loop_timeout(5)  # 5 second limit

def performance_test():
    """Measure function execution time."""
    start_time = get_timestamp()
    
    # Simulate work
    total = 0
    for i in range(1000000):
        total += i
    
    end_time = get_timestamp()
    execution_time = end_time - start_time
    
    print(f"Execution time: {execution_time:.2f}ms")
    print(f"Total: {total}")

performance_test()

Advanced Animation

Complex animations with easing and chaining.

class Animator:
    """
    Advanced animation controller.
    """
    
    def __init__(self):
        """Initialize animator."""
    
    def animate(self, element: Element, properties: dict, duration: int, 
               easing: str = 'linear') -> 'Animation':
        """
        Animate element properties.
        
        Args:
            element: Target element
            properties: Properties to animate with end values
            duration: Animation duration in milliseconds
            easing: Easing function name
            
        Returns:
            Animation object for control
        """
    
    def chain(self, *animations) -> 'AnimationChain':
        """Chain multiple animations in sequence."""
    
    def parallel(self, *animations) -> 'AnimationGroup':
        """Run multiple animations in parallel."""

class Animation:
    """Individual animation instance."""
    
    def start(self) -> None:
        """Start animation."""
    
    def pause(self) -> None:
        """Pause animation."""
    
    def resume(self) -> None:
        """Resume paused animation."""
    
    def stop(self) -> None:
        """Stop animation."""
    
    def on_complete(self, callback: Callable) -> 'Animation':
        """Set completion callback."""

Usage:

from browser.timer import Animator
from browser import document
from browser.html import DIV

# Create animator
animator = Animator()

# Create elements to animate
box1 = DIV("Box 1", style={
    'position': 'absolute',
    'width': '50px',
    'height': '50px',
    'background': 'red',
    'left': '0px',
    'top': '200px'
})

box2 = DIV("Box 2", style={
    'position': 'absolute', 
    'width': '50px',
    'height': '50px',
    'background': 'blue',
    'left': '0px',
    'top': '260px'
})

document.body <= box1
document.body <= box2

# Create animations
move_right = animator.animate(box1, {
    'left': '300px',
    'background': 'green'
}, 2000, easing='ease-out')

move_up = animator.animate(box2, {
    'top': '100px',
    'width': '100px',
    'height': '100px'
}, 1500, easing='ease-in-out')

# Chain animations
sequence = animator.chain(move_right, move_up)

# Parallel animations  
parallel = animator.parallel(
    animator.animate(box1, {'opacity': '0.5'}, 1000),
    animator.animate(box2, {'opacity': '0.5'}, 1000)
)

# Start animations with callbacks
move_right.on_complete(lambda: print("Box 1 finished moving"))
sequence.start()

def complex_animation():
    """Complex multi-stage animation."""
    
    # Stage 1: Move elements
    stage1 = animator.parallel(
        animator.animate(box1, {'left': '200px'}, 1000),
        animator.animate(box2, {'left': '200px'}, 1000)
    )
    
    # Stage 2: Rotate and scale
    stage2 = animator.parallel(
        animator.animate(box1, {
            'transform': 'rotate(180deg) scale(1.5)',
            'background': 'purple'
        }, 1500),
        animator.animate(box2, {
            'transform': 'rotate(-180deg) scale(0.8)',
            'background': 'orange'
        }, 1500)
    )
    
    # Stage 3: Return to original
    stage3 = animator.parallel(
        animator.animate(box1, {
            'left': '0px',
            'transform': 'rotate(0deg) scale(1)',
            'background': 'red'
        }, 2000),
        animator.animate(box2, {
            'left': '0px', 
            'transform': 'rotate(0deg) scale(1)',
            'background': 'blue'
        }, 2000)
    )
    
    # Chain all stages
    full_sequence = animator.chain(stage1, stage2, stage3)
    full_sequence.on_complete(lambda: print("Complex animation complete"))
    full_sequence.start()

# Trigger complex animation
from browser.html import BUTTON
from browser import bind

complex_btn = BUTTON("Start Complex Animation")

@bind(complex_btn, 'click')
def handle_complex(event):
    complex_animation()

document.body <= complex_btn

Timer Utilities

Helper functions for common timing patterns.

class Timer:
    """
    Timer utility class with advanced features.
    """
    
    def __init__(self):
        """Initialize timer."""
    
    def debounce(self, func: Callable, delay: int) -> Callable:
        """
        Create debounced function that delays execution.
        
        Args:
            func: Function to debounce
            delay: Delay in milliseconds
            
        Returns:
            Debounced function
        """
    
    def throttle(self, func: Callable, limit: int) -> Callable:
        """
        Create throttled function that limits execution rate.
        
        Args:
            func: Function to throttle  
            limit: Minimum interval between calls in milliseconds
            
        Returns:
            Throttled function
        """
    
    def countdown(self, seconds: int, callback: Callable, 
                 tick_callback: Callable = None) -> int:
        """
        Create countdown timer.
        
        Args:
            seconds: Countdown duration
            callback: Function to call when complete
            tick_callback: Function to call each second (receives remaining time)
            
        Returns:
            Timer ID for cancellation
        """

timer_utils = Timer()

Usage:

from browser.timer import Timer
from browser import document, bind
from browser.html import INPUT, DIV

timer = Timer()

# Debounced search function
search_results = DIV()
document.body <= search_results

def perform_search(query):
    """Simulate search operation."""
    print(f"Searching for: {query}")
    search_results.text = f"Results for: {query}"

# Debounce search to avoid excessive API calls
debounced_search = timer.debounce(perform_search, 500)  # 500ms delay

search_input = INPUT(placeholder="Type to search...")

@bind(search_input, 'input')
def handle_search_input(event):
    query = event.target.value
    if query.strip():
        debounced_search(query)

document.body <= search_input

# Throttled scroll handler
def handle_scroll():
    """Handle scroll events."""
    scroll_position = window.pageYOffset
    print(f"Scroll position: {scroll_position}")

# Throttle scroll events to improve performance
throttled_scroll = timer.throttle(handle_scroll, 100)  # Max 10 times per second

@bind(window, 'scroll')
def on_scroll(event):
    throttled_scroll()

# Countdown timer
countdown_display = DIV()
document.body <= countdown_display

def start_countdown():
    """Start 10-second countdown."""
    
    def on_tick(remaining):
        countdown_display.text = f"Countdown: {remaining} seconds"
    
    def on_complete():
        countdown_display.text = "Countdown finished!"
        print("Timer expired!")
    
    timer.countdown(10, on_complete, on_tick)

from browser.html import BUTTON

countdown_btn = BUTTON("Start 10s Countdown")

@bind(countdown_btn, 'click')
def handle_countdown(event):
    start_countdown()

document.body <= countdown_btn

Animation Easing

Built-in easing functions for natural animations.

# Available easing functions
EASING_FUNCTIONS = {
    'linear': 'linear progression',
    'ease': 'default ease',
    'ease-in': 'slow start',
    'ease-out': 'slow end', 
    'ease-in-out': 'slow start and end',
    'cubic-bezier': 'custom cubic bezier curve'
}

def create_easing(p1: float, p2: float, p3: float, p4: float) -> str:
    """
    Create custom cubic-bezier easing function.
    
    Args:
        p1, p2, p3, p4: Bezier curve control points
        
    Returns:
        CSS cubic-bezier string
    """

This comprehensive timing system enables sophisticated time-based functionality and smooth animations for creating engaging and responsive user interfaces in Brython applications.

Install with Tessl CLI

npx tessl i tessl/pypi-brython

docs

ajax-networking.md

browser-integration.md

cli-tools.md

html-elements.md

index.md

runtime-engine.md

storage.md

timers-animation.md

ui-framework.md

websocket.md

tile.json