Skip to content

improve keyframe animation#857

Merged
pissang merged 42 commits into
nextfrom
animation-keyframe-easing
Dec 20, 2021
Merged

improve keyframe animation#857
pissang merged 42 commits into
nextfrom
animation-keyframe-easing

Conversation

@pissang
Copy link
Copy Markdown
Contributor

@pissang pissang commented Dec 15, 2021

This PR aims to improving the keyframe based animation in zrender and https://github.com/apache/echarts on top of it.

There are no big changes. All changes are minor but can imporve the flexibity of keyframe animation.

The ultimate goal is keyframe animation in zrender can have enough flexibity to display a very complex lottie animation.

Here is the full change list:

Add easing configuration for each keyframe

Instead of configuring easing for the whole animation. We support easing configuration for each frame now. It can provide more granular timing functions.

Use case

el.animate()
  .when(200, {
    x: 100
  }, 'cubicOut')
  .when(200, {
    x: 10
  }, 'cubicIn')
  .start();

Add cubic-bezier timing functions

Instead of using builtin easing function or custom callback functions. We add more commonly used cubic-bezier timing function which has same format with CSS.

Use case

el.animate()
  .when(200, {
    x: 100
  }, 'cubic-bezier(0.32, 0, 0.67, 0)')
  .start();

Support animation on gradient color

Previously we can only do interpolation between solid colors with string. Now we can have animation between gradient colors with arbitrary color stops.

But animation between gradient color and solid color are not supported yet.

Use case

el.style.fill = {
  type: 'linear',
  x: 0, y: 0, x2: 1, y: 0,
  colorStops: [{
    offset: 0,
    color: 'red'
  }, {
    offset: 1,
    color: 'black'
  }]
};

el.animateTo({
  style: {
    fill: {
      type: 'linear',
      x: 0, y: 0, x2: 1, y: 0,
      colorStops: [{
        offset: 0,
        color: 'white'
      }, {
        offset: 1,
        color: 'blue'
      }]
    }
  }
})

Support discrete animation

Previously if one property can not be animated, like ignore, it will skip the animation and assign the final value directly.

Now we can have discrete animation on these properties.

Use case

el.animate()
  // Hide at first
  .when(0, {
    ignore: true
  })
  // Start to show after 300ms.
  .when(300, {
    ignore: false 
  })
  // Hide again after 500ms.
  .when(500, {
    ignore: true
  })
  .start()

Support negative keyframe time

Negative keyframe exist in the lottie animations. It's useful when we wan it to be in the intermediate frame on the initial state.

Use case

el.animate()
  .when(-100, {
    x: 100
  })
  // When animation is started. The initial state will be interpolated between -100 and 100. Which will lead to the x to 150
  .when(100, {
    x: 200
  })
  .start();

Support anchorX and anchorY

anchorX and anchorY is used in some animation systems like lottie. It will translate the shape to the anchor before applying other transforms. The difference between anchor and origin is that origin won't translate the shape. Before using anchor, we need an extra group to do the anchor transform.

const anchorGroup = {
  x: -anchorX,
  y: -anchorY,
  children
};
const rootGroup = {
  children: [anchorGroup]
  ...otherTransforms
}

Now we can just use one group:

const rootGroup = {
  anchorX, anchorY,
  ...otherTransforms
}

Deprecated functions

These unused functions are removed to reduce the complexity.

  • Catmull-Rom spline timing function is removed.

  • Polyfill of dashed line in the browsers IE <= 10 is dropped.

  • Clip#gap is removed.

  • animation#onframe callback is removed. Use animation#on('frame') instead.

  • zrender#pathToImage

trajnisz and others added 29 commits November 18, 2021 21:14
…k 'Latin Extended-A' - European characters)
Expanded UNICODE range for Latin characters  from 33-255 to 33-383
fix(pattern): fix matrix order & fix pattern create failed error
To compatible with the environment that not support css animation
Still set attributes once when all values in keyframes are same.
For the case:
el.x = 0;
el.animate().when(0, {x: 100}.when(100, {x: 100}

Ensure the attribute will be set instead of ignored.
Which means the initial value is before the animation start.
@pissang pissang marked this pull request as draft December 15, 2021 07:12
@pissang pissang marked this pull request as ready for review December 16, 2021 05:38
@pissang pissang requested review from 100pah and plainheart December 16, 2021 05:39
@Ovilia
Copy link
Copy Markdown
Member

Ovilia commented Dec 16, 2021

Looks promising! 🔥

Comment thread zrender Outdated
Comment thread src/Element.ts Outdated
Copy link
Copy Markdown
Collaborator

@plainheart plainheart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@pissang pissang merged commit f64bdb9 into next Dec 20, 2021
@pissang pissang deleted the animation-keyframe-easing branch December 20, 2021 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants