Skip to content

ConnectedAnimation

Header: winui/ui/ConnectedAnimation.hpp.

A connected animation: one element flying from where it was (the source, snapshotted by ConnectedAnimationService::prepare_to_animate()) to where its counterpart is (the destination, named by try_start()), usually across a page navigation.

The service owns it, and you reach it by reference or pointer. It lives until it completes or is canceled. One that is never started times out two seconds after being prepared. While it runs, a crossfade of the two snapshots moves from the source's rect to the destination's, and by default scales with it. It is drawn above the tree and below popups. The destination stays hidden until the flight lands.

Example:

// On the list page, just before navigating away:
void leave_list(ui::ImageControl& thumbnail)
{
    window.connected_animation_service().prepare_to_animate("ForwardConnectedAnimation", thumbnail);
}

// On the detail page, once its tree is in the window:
void arrive_at_detail(ui::ImageControl& detail_image, ui::TextControl& detail_title)
{
    ui::ConnectedAnimationService& service = window.connected_animation_service();
    if (ui::ConnectedAnimation* animation = service.animation("ForwardConnectedAnimation"))
    {
        animation->set_flight_path(ui::ShortFlightPath{});
        animation->on_completed([] { /* the destination is showing again */ });
        animation->try_start(detail_image, {&detail_title}); // the title flies in alongside
    }
}

ui::ConnectedAnimation

A connected animation: one element flying from where it was (the source, snapshotted by ConnectedAnimationService::prepare_to_animate()) to where its counterpart is (the destination, named by try_start()), usually across a page navigation.

The service owns it, and you reach it by reference or pointer. It lives until it completes or is canceled. One that is never started times out two seconds after being prepared. While it runs, a crossfade of the two snapshots moves from the source's rect to the destination's, and by default scales with it. It is drawn above the tree and below popups. The destination stays hidden until the flight lands.

Example:

// On the list page, just before navigating away:
void leave_list(ui::ImageControl& thumbnail)
{
    window.connected_animation_service().prepare_to_animate("ForwardConnectedAnimation", thumbnail);
}

// On the detail page, once its tree is in the window:
void arrive_at_detail(ui::ImageControl& detail_image, ui::TextControl& detail_title)
{
    ui::ConnectedAnimationService& service = window.connected_animation_service();
    if (ui::ConnectedAnimation* animation = service.animation("ForwardConnectedAnimation"))
    {
        animation->set_flight_path(ui::ShortFlightPath{});
        animation->on_completed([] { /* the destination is showing again */ });
        animation->try_start(detail_image, {&detail_title}); // the title flies in alongside
    }
}

ConnectedAnimation

ConnectedAnimation(const ConnectedAnimation&) = delete

Non-copyable: the service owns every animation.

operator=

ConnectedAnimation& operator=(const ConnectedAnimation&) = delete

Non-copyable: the service owns every animation.

try_start

bool try_start(Element& destination, std::vector<Element*> coordinated = {})

Animate into destination, and fly the coordinated elements in alongside it. They start from where they would sit relative to the source and fade in. The flight begins after the next layout, when the destination is snapshotted and hidden. Returns false and does nothing when the animation was already started, canceled or timed out, or when the destination is the source itself. A destination destroyed before that layout, or laid out with zero size, cancels the animation.

cancel

void cancel()

Drop it, snapshot and all; a hidden destination shows again.

flight_path

const std::optional<FlightPath>& flight_path() const

The flight path; nullopt (the default) is an ArcFlightPath.

set_flight_path

void set_flight_path(std::optional<FlightPath> path)

Set before try_start(); a running flight keeps the path it began with.

is_scale_animation_enabled

bool is_scale_animation_enabled() const

True (the default) scales the snapshots from the source's size to the destination's. False keeps their own sizes, so they only move, centered on each other.

set_scale_animation_enabled

void set_scale_animation_enabled(bool enabled)

Set before try_start().

on_completed

void on_completed(Callback<void()> handler)

Fired when the animation has played (not when it is canceled or times out). Replaces any previous handler.

state

ConnectedAnimationState state() const

The current state; Prepared right after prepare_to_animate().

source_rect

const Rect& source_rect() const

The source's rect when it was prepared (window coordinates).

destination_rect

const Rect& destination_rect() const

The destination's rect once running (window coordinates); empty before that.

class ConnectedAnimationService

The per-window registry of connected animations, keyed by name, and the layer that draws them.

Each Window owns one (Window::connected_animation_service()) and runs and draws its animations. An app only prepares animations and looks them up. Keys are strings the app chooses, and both pages use the same key.

Example:

// On the list page, just before navigating away:
void leave_list(ui::ImageControl& thumbnail)
{
    window.connected_animation_service().prepare_to_animate("ForwardConnectedAnimation", thumbnail);
}

// On the detail page, once its tree is in the window:
void arrive_at_detail(ui::ImageControl& detail_image, ui::TextControl& detail_title)
{
    ui::ConnectedAnimationService& service = window.connected_animation_service();
    if (ui::ConnectedAnimation* animation = service.animation("ForwardConnectedAnimation"))
    {
        animation->set_flight_path(ui::ShortFlightPath{});
        animation->on_completed([] { /* the destination is showing again */ });
        animation->try_start(detail_image, {&detail_title}); // the title flies in alongside
    }
}

ConnectedAnimationService

ConnectedAnimationService() = default

An empty service; a Window constructs its own.

ConnectedAnimationService

ConnectedAnimationService(const ConnectedAnimationService&) = delete

Non-copyable: animations point back at their service.

operator=

ConnectedAnimationService& operator=(const ConnectedAnimationService&) = delete

Non-copyable: animations point back at their service.

prepare_to_animate

ConnectedAnimation& prepare_to_animate(std::string key, Element& source)

Snapshot source now, under key, and cancel any animation already prepared under it. The returned animation lives until it completes, is canceled or times out, and animation() finds it until then.

animation

ConnectedAnimation* animation(const std::string& key) const

The animation prepared under key and not yet finished, or nullptr.

default_duration

Duration default_duration() const

The duration ArcFlightPath and StraightFlightPath use (300 ms by default).

set_default_duration

void set_default_duration(Duration duration)

Applies to animations that start afterwards.

default_easing

const EasingFunction& default_easing() const

The easing ArcFlightPath and StraightFlightPath use, a (0.8,0)-(0.2,1) cubic Bézier by default.

set_default_easing

void set_default_easing(EasingFunction easing)

Applies to animations that start afterwards.

active

bool active() const

Whether any animation is prepared or running, so something may be on screen.

struct StraightFlightPath

A straight move with the service's default duration and easing (ConnectedAnimationService::default_duration(), default_easing()).

struct ShortFlightPath

A straight, decelerating 200 ms move with (0.1,0.9)-(0.2,1) easing. Use it for back navigation.

struct ArcFlightPath

The default flight path. The element dips 80 DIPs downward and back during a 300 ms move with (0.8,0)-(0.2,1) cubic Bézier easing. When its size does not otherwise change, it scales up by 10 % at the lowest point.

Example:

void prepare_flight(ui::Element& source)
{
    ui::ConnectedAnimation& animation =
        window.connected_animation_service().prepare_to_animate("ForwardConnectedAnimation", source);
    animation.set_flight_path(ui::ArcFlightPath{.shadow = false});
}

Field Type Default
shadow bool true A shadow under the element as it flies.

Enumerations

ConnectedAnimationState

enum class ConnectedAnimationState

The stage a ConnectedAnimation is in.

Value
Prepared snapshot taken, waiting for try_start()
Started try_start() called, waiting for the destination's layout
Running flying; the destination is hidden
Complete played to the end; on_completed() has fired
Canceled cancel()ed, replaced by a new prepare, or timed out

Aliases

FlightPath

using ui::FlightPath = std::variant<ArcFlightPath, ShortFlightPath, StraightFlightPath>

One of the three paths a connected animation flies.