Animation & Playback ==================== Browser Viewer -------------- The simplest way to display an animation is ``canvas.show()``, which automatically parses CLI arguments and either opens the browser viewer or exports to a file: .. code-block:: python canvas.show(end=5) .. list-table:: :header-rows: 1 :widths: auto * - CLI Flag - Default - Description * - ``-v``, ``--verbose`` - off - Enable debug logging * - ``--fps FPS`` - 60 - Frames per second * - ``--port PORT`` - 8765 - WebSocket server port * - ``-o``, ``--output PATH`` - none - Export to file (format inferred from extension: ``.mp4``, ``.gif``, ``.svg``, ``.png``) * - ``-d``, ``--duration SECS`` - none - Animation duration in seconds * - ``--start SECS`` - 0 - Start time * - ``--end SECS`` - none - End time * - ``--hot-reload`` - off - Re-run script on file save .. tip:: Examples: .. code-block:: bash python my_scene.py # open browser viewer python my_scene.py -v # verbose logging python my_scene.py --fps 30 # set frame rate python my_scene.py --port 9000 # custom port python my_scene.py -o out.mp4 # export to video python my_scene.py -o frame.svg # export single SVG frame python my_scene.py -d 5 # set duration to 5 seconds You can also call ``browser_display()`` directly for more control: .. code-block:: python canvas.browser_display(start=0, end=None, fps=60, port=8765, hot_reload=False) Keyboard Shortcuts ------------------ .. list-table:: :header-rows: 1 :widths: auto * - Key - Action * - **Space** / **P** - Pause / Resume * - **R** - Restart from beginning * - **,** / **.** - Step backward / forward one frame * - **Left** / **Right** - Previous / next section * - **-** / **+** / **Up** / **Down** - Slower / faster (0.25x increments) * - **0**--**9** - Jump to 0%--90% of the animation * - **Home** / **End** - Jump to start / end * - **F** - Reset zoom to fit * - **S** - Save current frame as SVG * - **Shift+S** - Save current frame as PNG * - **C** - Copy SVG to clipboard * - **L** - Toggle loop * - **B** - Cycle background (dark / white / checker) * - **Ctrl+B** - Add / remove bookmark * - **[** / **]** - Previous / next bookmark * - **H** - Hide / show toolbars * - **G** - Toggle grid overlay * - **I** - Inspect mode (nearest object) * - **M** - Measure tool (click two points) * - **N** - Toggle snap mode * - **D** - Toggle debug panel * - **?** - Help overlay * - **Q** - Quit * - **Scroll wheel** - Zoom in/out at cursor position Debug Panel ----------- Press **D** to toggle the debug panel. It shows: - Current time and frame number - Total frames - List of visible objects at the current time Snap Mode --------- Press **N** to toggle snap mode. When enabled, moving the mouse over the SVG canvas snaps the cursor to nearby object points (centres, corners, etc.), shown with a visual indicator. Sections -------- Sections let you pause the animation at specific times, useful for presentations: .. code-block:: python canvas.add_section(3) # pause at t=3 canvas.add_section(6) # pause at t=6 During playback, the animation pauses at each section boundary. Press **Arrow Right** to continue to the next section. .. admonition:: Example: sections demo :class: example .. raw:: html Objects appear in phases separated by section breaks. During playback the animation pauses at each ``add_section`` time. .. literalinclude:: ../../examples/reference/anim_sections.py :language: python Playback Speed -------------- Speed can be adjusted during playback with **+** / **-** keys, or via the toolbar buttons. The current speed and FPS are shown in the toolbar. .. admonition:: Example: animation timing :class: example .. raw:: html The same shift animation with different ``start``/``end`` durations. Shorter intervals mean faster motion. .. literalinclude:: ../../examples/reference/anim_speed.py :language: python Static Pictures --------------- Pass ``end=0`` to display a single static frame with no animation: .. code-block:: python canvas.browser_display(end=0) ---- Exporting --------- SVG Frame ^^^^^^^^^ .. code-block:: python canvas.write_frame(time=2.5, filename='frame.svg') All Sections as SVG ^^^^^^^^^^^^^^^^^^^ .. code-block:: python canvas.export_sections(prefix='slide') # Writes slide_000.svg, slide_001.svg, ... for each section boundary PNG ^^^ Export a single frame as PNG (requires ``cairosvg``): .. code-block:: python canvas.export_png(time=0, filename='frame.png', width=None, height=None) ``width`` and ``height`` control the output resolution. If omitted, the canvas dimensions are used. Video (MP4) ^^^^^^^^^^^ Export the animation as an MP4 video (requires ``cairosvg`` and ``ffmpeg``): .. code-block:: python canvas.export_video(filename='animation.mp4', start=0, end=None, fps=60) .. note:: Video export requires **ffmpeg** to be installed and available on your ``PATH``. On Debian/Ubuntu: ``sudo apt install ffmpeg``. On macOS: ``brew install ffmpeg``. On Arch: ``sudo pacman -S ffmpeg``. Animated GIF ^^^^^^^^^^^^ Export the animation as a GIF (requires ``cairosvg`` and ``Pillow``): .. code-block:: python canvas.export_gif(filename='animation.gif', start=0, end=None, fps=30, scale=1.0, loop=0) .. list-table:: :header-rows: 1 :widths: auto * - Parameter - Description * - ``scale`` - Scale factor for output dimensions (e.g. ``0.5`` for half size) * - ``loop`` - Number of loops (``0`` = infinite) .. admonition:: Example: static frame export :class: example .. raw:: html A composed scene exported as a single SVG frame with ``write_frame``. .. literalinclude:: ../../examples/reference/anim_export.py :language: python ---- Hot Reload ---------- Enable hot reload to automatically re-run the script when you save changes: .. code-block:: python canvas.browser_display(hot_reload=True) The browser stays open and updates live -- useful during development.