# Shared Element Animation

original App We often see such interactions, such as from the product list page into the details page process, the product picture leaps between the pages, making the transition effect smoother, another case is the image preview magnification function of WeChat Moments. in Skyline Rendering mode, which we call shared element animation, is available through share-element Components to implement.

In a continuous Skyline When pages jump, between pages key The same share-element The nodes will generate leap effects, and the developer can customize the interpolation method and animation curve. Usually act on the picture, in order to ensure the animation effect, before and after the page share-element The child node structure should be as consistent as possible.

# Experience immediately

Scan the code to open the Mini Program example, interactive animation - Basic components - Shared Element Animation Can experience.

# Methods of Use

attribute type Default value Required Introductions Minimum version
key string yes Mapping tag, unique within the page 2.29.2
transition-on-gesture boolean false no Whether to animate when the gesture returns 2.29.2
shuttle-on-push string to no Appoint push The Leap Thing of Stage 2.30.2
shuttle-on-pop string to no Appoint pop The Leap Thing of Stage 2.30.2
rect-tween-type string materialRectArc no Animation interpolation curve 2.30.2
on - frame worklet callback no Animation Frame Callback 2.30.2

Assume A Pages and B The page has a corresponding share-element assembly

  1. push Stage: Through wx.navigateTo by A Get into B, said A The source page (from page),B For the target page (to page)
  2. pop Stage: Through wx.navigateBack by B return A♪ at this point B For the source page (from page), A For the target page (to Page)

# Designated Leap Object

For a selected source or target page share-element As a leap.

Since the component involves two pages, here the target page share-element Component-specified attributes prevail

  1. push stage: Default Adoption B Page share-element Components to make the leap, set the properties shuttle-on-push=from Can be switched to A Pages.
  2. pop stage: Default Adoption A Page share-element Component, Set Properties shuttle-on-pop=from Can be switched to B Pages.

It should be noted that on - frame The callback is always found in the share-element Triggered on the component.

# Animation Frame Callback

Shared element animation is based on the source page share-element In the rectangular box as the starting point, the target page share-element In the rectangular box as the end point, interpolation calculation process, animation time and page routing time consistent.

enum FlightDirection {
  push = 0,
  pop = 1
}

Interface Rect {
  top: number,
  right: number,
  bottom: number,
  left: number,
  width: number,
  height: number
}

Interface ShareElementFrameData {
  // Animation Progress, 01
  progress: number,
  // In animation direction, push; | pop
  direction: FlightDirection
  // Source page share-element Container size
  begin: Rect,
  // Target Page share-element Container size
  end: Rect,
  // Dimensions of the Current Frame Leap Object Container Calculated by Frame
  current: Rect,
}

type ShareElementOnFrameCallback = (data: ShareElementFrameData) => undefined | Rect

The developer can pass on - frame Callback to customize the interpolation method.ShareElementFrameData Contains the beginning and end positions, and the frame according to the specified animation curve rect-tween-type And Current Progress progress Calculated current Location.

The default interpolation is for Rect of LTWH Linear interpolation, respectivelyThe. When on - frame return undefined The real time position of the leap object in the current frame is determined by current Determined, the developer may return the otherwise computed Rect Object is overwritten.

const lerp = (begin: number, end: number, t: number) => {
  'worklet'
  return Begin + (end - Begin) * t
}

const lerpRect = (begin: Rect, end: Rect, t: number) => {
  'worklet'
  const left = lerp(begin.left, end.left, t)
  const top = lerp(begin.top, end.top, t)
  const width = lerp(begin.width, end.width, t)
  const height = lerp(begin.height, end.height, t)
  const right = left + width
  const bottom = top + height

  return {
    left,
    top,
    right,
    bottom,
    width,
    height
  }
}

# Animation interpolation curve

In addition to customizing the interpolation method, you can also customize the animation curve. The default animation curve is [cubic-bezier (0.4, 0.0, 0.2, 1.0)](https://cubic-bezier.com /#.4,0,.2,1), recorded as fastOutSlowIn

when rect-tween-type When set to the following type,The default interpolation method is for Rect of LTWH Linear interpolation, respectively

In addition,rect-tween-type Also supports two special classes of enumeration values for which the animation curve is still fastOutSlowIn, but the interpolation method is different, the trajectory is an arc.

  • Materialrectarc: Rectangular Diagonal Animation
  • materialRectCenterArc:[Radial animation](https://web.archive.org/web/20180223140424/https://Material.io /guidelines/motion/transforming-material.html#)

# Working principle

Below with push Process as an example of the various stages of shared element animation.

Note: Actually during the animation share-element The nodes themselves do not animate; they move their children.

# Before the animation begins

Target page not yet rendered, created on top of all pages overlay Layer, the leap object will be in the overlay Layer for animation.

# Animation Start Time

call wx.navigateTo Animation is triggered when a new page is pushed,progress = 0 The following actions occur at the moment

  1. Target header frame rendering, the frame calculates the target share-element Node location size.
  2. source share-element The node is off the screen (not displayed).
  3. Will target share-element Node move overlay Layer, as a leaping object, the position and size of the homologous share-element Node.

# During the animation

According to the specified interpolation mode and the animation curve, the target share-element in overlay Layer animates, transitioning from the start to the end position.

# Animation End Time

progress = 1 Time to aim. share-element from overlay Layer moves to the destination page and appears at the destination location.

# Note

  • Skyline version share-element No need to combine page-container use
  • to share-element Component Settings paddingjustify-content Styles that affect the layout of child nodes will not take effect
  • Can be combined with the page life cycle onRouteDone Do some state recovery at the time of route completion

# Q & A

# Q1: Set up the same Key, but do not see the leap animation

The shared element animation needs to ensure that the first frame of the next page is created share-element Node, and set the Key is used to calculate the target location.

If it is through setData Set, may miss the first frame. In this case, you can use Component The constructor constructs the next page, as long as the component attached Before the life cycle (including) through setData Set it up, it will render in the first frame.

# Q2: During the leap, the child nodes do not follow the amplification/narrow

During the animation process, the size and position of the leap container will change continuously, and if the children want to adapt to the change, they need to use the percentage layout instead of writing a fixed width and height.

<!-- Because of the sub view Fixed size, only the position changes during the leap, the size remains the same -->
<share-element key="portrait">
  <view style="width: 50px height: 50px"></view>
</share-element>


<!-- Because of the sub view Set as large as the parent node, position and size will change during the leap -->
<share-element key="portrait" style="width: 50px height: 50px">
  <view style="width: 100% height: 100%"></view>
</share-element>

# Q3: many share-element Animate together, covering the hierarchy issues

The Leap Thing in overlay Layers are animated, with layers above all pages. Leaps and bounds in the order they are defined in the page component treeDFS Traversal), the later the higher the level.

# Q4: Return animation not seen when custom route gesture returns

The components must first be set transition-on-gesture=true Property. While the custom route gesture returns, only the call to the startUserGesture Interface before the shared element animation is triggered.

# Q5: The Relationship between Shared Element Animation and Route Animation

Shared elements start and end with the page route animation. If you set the page entry curve for the custom route and rect-tween-type Consistent, then onFrame Returned progress Values are also associated with PrimaryAnimation.value Values are always consistent.

# Example usage

# Basic usage

Product List Page

<block wx:for="{{list}}" wx:key="id">
  <share-element key="box" transition-on-gesture>
    <image
    src="{{src}}"
    mode="aspectFill"
    />
  </share-element>
</block>

Product Detail Page

<share-element key="box" transition-on-gesture>
  <image
  src="{{src}}"
  mode="aspectFit"
  />
</share-element>

Sample Code Snippets - Basics

Can experience the effect in the developer tools, here need to pay attention to the image mode Different effects.

# Advanced usage

To imitate WeChat Moments picture preview zoom function, for example, introduced through the frame callback to solve the picture mode Different problems caused by the jump. Related functions have been encapsulated into aniamted-image Component, the developer can modify it on the basis of which.

Here is a brief introduction to the core ideas:

  1. Always with list page share-element For Flying Objects
  2. adopt on - frame Overwrite the position size of the leap container so that it is full overlay layer
  3. Determine the position size of the starting and ending containers based on the actual space occupied by the picture, rather than share-element The space occupied by nodes
  4. Use thumbnails during the leap, and replace the HD image after downloading.

The default calculation is to share-element Nodes occupy the space to determine the beginning and end position, will produce jump.

The actual space occupied by the picture to determine the beginning and end position, always using a single mode Effect, will not produce a jump.

Use the latest nightly Tool Preview, Mobile Android 8.0.33 Version.

Sample code snippet - Advanced