Ember Animated

repository·master·Indexed 42 days ago

https://github.com/ember-animation/ember-animated

A library for handling animations within Ember.js applications (v4.8+). It provides a foundation for programmatic animations via Motion and Tween, Glimmer Template Syntax (GTS) components for animating lists and conditional blocks, and specialized motion functions such as move(), fadeIn(), fadeOut(), resize(), and scale(). Includes concurrency and scheduler utilities like rAF, spawn, and parallel to manage animation timing and execution.

Tokens
8.7K
Snippets
38
Records
57
Agent score
53%

What's inside Ember Animated

  1. What are sprites in Ember Animated?

    master

    In Ember Animated, a sprite is an HTML element packaged with additional metadata such as width, height, CSS styles, and historical bounds. Sprites allow developers to animate HTML elements and respond to state changes (like elements entering or leaving the DOM) without manual bookkeeping of element positions.

    By using sprites, you can animate elements from a starting point to a final location, or from a current location to an exit point, as well as smoothly transition elements that remain in the DOM during a state change.

  2. How sprites animate between components using receivedSprites and sentSprites

    master

    When elements are moved from one list or component to another (e.g., moving an item from a 'Going' list to a 'Not Going' list), they can be treated as receivedSprites and sentSprites.

    Ember Animated tracks the initial and final bounds of a sprite. If these bounds are interchanged, the library identifies the sprite as traveling between two specific lists. This allows for smooth transitions even when an element is being removed from one container and simultaneously inserted into another.

    • receivedSprites: A sprite is a receivedSprite on the destination list when its final bounds match its initial bounds (it is arriving at its new location).
    • sentSprites: A sprite is a sentSprite on the source list when its initial bounds match its final bounds (it is leaving its old location).
  3. Use `resize` vs `scale` for size changes

    master

    When animating the size of a sprite, you have two primary options:

    1. resize: Animates the height and width properties. It supports length values (like px or cm) and percentages. This is the default motion used by animated-container.
    2. scale: Applies CSS transforms to animate the size.

    Recommendation: Use scale instead of resize whenever possible, as scale uses CSS transforms and avoids triggering browser reflow, leading to better performance.

  4. Use rules for data-dependent animations

    master

    The rules property allows you to select different animated transitions based on changes in data. When a component has both rules and a transition, the rules take precedence.

    Rules work by comparing the previous state (oldList) to the new state (newList). You can define logic that evaluates these values to return a specific transition name or object.

    Example Logic:

    • If newList[0] > oldList[0], use the toUp transition.
    • If newList[0] < oldList[0], use the toDown transition.
    // Conceptual logic for a rules function
    // rules(oldList, newList) -> transition
    
    if (newList[0] > oldList[0]) {
      return 'toUp';
    } else if (newList[0] < oldList[0]) {
      return 'toDown';
    }
  5. What are Motions in ember-animated

    master

    A motion animates the change in an attribute value of a single sprite. It is used to smoothly transition a sprite from one state to another (e.g., changing color, size, or position) rather than having the sprite jump abruptly between values.

    Usage Pattern: Each motion takes a sprite as the first argument and an options object as the second argument. Motions can also accept from and to arguments to explicitly define the initial and final attribute values.

    motion(sprite, options) or motion(sprite, { from: value, to: value })

  6. Handle animation interruption cases

    master
    Animations in ember-animated can be interrupted. When an animation is interrupted, the state of the animated element changes. For instance, if an email is in the process of being a removedSprite (animating out) but is then restored (e.g., via an 'Undo' action), it transitions to a keptSprite state instead of completing its removal animation.
  7. What are transitions in ember-animated?

    master

    A transition defines how sprite categories animate when moving from one state to another. You can assign specific motions to different sprite categories, such as insertedSprites, keptSprites, or removedSprites.

    Key characteristics of transitions:

    • Interruptible: If a sprite's state changes while a transition is already in progress, the animation can reverse or change direction immediately (e.g., an 'undo' action reversing a movement).
    • State-driven: Transitions run every time the state of a sprite changes.
    • Category-based: You can target specific lifecycle stages of a sprite (like when it is first added to a list) to apply specific animations.
  8. Understand the different categories of sprites

    master

    Ember Animated categorizes sprites based on their lifecycle during a DOM change and the specific bounding data they store. This data is used to drive animations.

    Sprite Categories

    1. insertedSprites: Elements that are entering or being inserted into the DOM. They store their final bounds, which can be used to animate the element from a starting point (e.g., off-screen) to its final position.
    2. removedSprites: Elements that are exiting or being removed from the DOM. They store their initial bounds, which can be used to animate the element from its last known position to a final exit position.
    3. keptSprites: Elements that exist in the DOM both before and after a state change. They store both initial and final bounds, allowing them to animate smoothly between their old and new positions.

    Note: sentSprites and receivedSprites are also categories used when animating between components, but they are handled in the 'Animating between components' documentation.

    Data Summary

    NameInitial BoundsFinal Bounds
    insertedSprites❌✅
    keptSprites✅✅
    removedSprites✅❌
  9. Install and set up the test-app

    master

    To set up the test-app environment for development, ensure you have Git, Node.js, pnpm, Ember CLI, and Google Chrome installed. Follow these steps to clone the repository and install dependencies:

    1. Clone the repository.
    2. Navigate to the test-app directory.
    3. Install dependencies using pnpm.
    4. Start the development server.
    git clone https://github.com/ember-animation/ember-animated.git
    cd ember-animated/test-app
    pnpm install
    ember s
  10. Use ember-animated in templates (GTS/GJS)

    master

    Ember Animated provides components and control structures for animations.

    Naming Convention:

    • Components (e.g., AnimatedBeacon, AnimatedContainer, AnimatedOrphans) use PascalCase imports.
    • Control Structures (e.g., animatedEach, animatedIf, animatedValue) use camelCase imports.

    You can import these from their specific component paths or from the top-level ember-animated module if your build environment supports tree-shaking.

    Available Features:

    • AnimatedBeacon: A component for triggering animations.
    • AnimatedContainer: A component to wrap animated content.
    • AnimatedOrphans: A component to handle orphaned elements.
    • animatedIf: A control structure for conditional animations.
    • animatedEach: A control structure for animating lists.
    • animatedValue: A control structure for animating changes to a specific value.
    import AnimatedBeacon from 'ember-animated/components/animated-beacon';
    import AnimatedContainer from 'ember-animated/components/animated-container';
    import animatedEach from 'ember-animated/components/animated-each';
    import animatedIf from 'ember-animated/components/animated-if';
    import AnimatedOrphans from 'ember-animated/components/animated-orphans';
    import animatedValue from 'ember-animated/components/animated-value';
    
    <template>
      <AnimatedBeacon @name="one" />
      <AnimatedOrphans/>
    
      <AnimatedContainer>
        {{#animatedIf this.showThing use=this.transition}}
          <div class="message" {{on "click" this.toggleThing}}>
            Hello!
          </div>
        {{/animatedIf}}
      </AnimatedContainer>
    
      <AnimatedContainer>
        {{#animatedEach this.items use=this.transition duration=2000 as |item|}}
          <div data-test-item={{item}} {{on "click" (fn this.removeItem item)}}>
            {{item}}
          </div>
        {{/animatedEach}}
      </AnimatedContainer>
    
      <AnimatedContainer>
        {{#animatedValue this.counter rules=this.rules duration=100 as |v|}}
          <span class="numbers">{{v}}</span>
        {{/animatedValue}}
      </AnimatedContainer>
    </template>