The explode transition

explode lets you break apart your old and new templates and animate the pieces separately. First we show examples, and then below we document all the options in detail.

Explode Demo #1

Click the button to see the demo:

The transition rule:

this.transition(
  this.childOf('#explode-demo-1'),
  this.use(
    'explode',
    {
      pickOld: 'h3', // Find an "h3" in the old template. This
      // can be any CSS selector.

      use: ['toUp', { duration }], // And animate it upward. This can
      // be any arbitrary transition, and
      // its optional parameters.
    },
    {
      pickNew: 'h3', // Find an "h3" in the new template

      use: ['toDown', { duration }], // And animate it downward.
    },
    {
      // For everything else that didn't match the above, use a
      // fade. I'm giving the fade half as much duration because fade
      // includes both fading out and fading in steps, each of which
      // spends `duration` milliseconds.
      use: ['fade', { duration: duration / 2 }],
    },
  ),
);

The template:

<div id="explode-demo-1">
  <button type="button" {{on "click" this.toggleDetail}}>Toggle Detail View</button>
  {{#liquid-if predicate=this.showDetail}}
    <div class="details">
      <h3>Details</h3>
      <p>
        Bacon ipsum dolor amet shank pork belly boudin flank
        prosciutto alcatra andouille pig short ribs biltong kevin
        salami tail turkey beef ribs.
      </p>
    </div>
  {{else}}
    <div class="overview">
      <h3>Welcome</h3>
      <p>This is the overview.</p>
    </div>
  {{/liquid-if}}
</div>

Explode Demo #2

Click "Shuffle":

The transition rule:

this.transition(
  this.childOf('#explode-demo-2'),
  this.use('explode', {
    matchBy: 'data-photo-id', // matchBy will look for the same
    // HTML attribute value in both
    // the old and new elements, and
    // for each matching pair, it
    // runs the given transition.

    // fly-to is a built in transition that animate the element
    // moving from the position of oldElement to the position of
    // newElement.
    use: ['fly-to', { duration, easing: 'spring' }],
  }),
);

The template:

<div id="explode-demo-2">
  <button type="button" {{on "click" this.shuffle}}>Shuffle</button>
  <LiquidBind @value={{this.photos}} as |photosVersion|>
    {{#each photosVersion key="id" as |photo|}}
      {{! template-lint-disable require-valid-alt-text }}
      <img src={{photo.url}} alt="a random person" data-photo-id={{photo.id}}>
    {{/each}}
  </LiquidBind>
</div>

API details

explode accepts any number of arguments. Each argument must be an object. Each object describes one piece of the transition.

Each piece must have a use property, which can be:

  • the name of another transition. Example: "toLeft"
  • a list whose first element is the name of another transition and whose remaining members are the arguments for that transitions. Example: ["toLeft", { duration: 100 }]
  • a function that directly implements a transition. Example: function(){ return animate(this.newElement, { opacity: 0 }); }
  • a list whose first element is a function that directly implements a transition and whose remaining members are arguments for the function. Example: [myTransitionFunction, { duration: 400 }]

Each piece may also have one of these options:

  • a pick property whose value is a CSS selector that will be matched against both the old and new elements.
  • a pickOld property whose value is a CSS selector that will be matched against the old elements. May be combined with pickNew.
  • a pickNew property whose value is a CSS selector that will be matched against the old elements. May be combined with pickOld.
  • a matchBy property whose value is the name of an HTML attribute that will be matched against both old and new elements for pairwise transitions.

A piece that has only a use and no further options may be used to control everything else that doesn't match another section.