动画
概述
🌐 Overview
Ionic Animations 是一种工具,使开发者能够以与平台无关的方式创建复杂的动画,而不需要特定的框架或 Ionic 应用。
🌐 Ionic Animations is a tool that enables developers to create complex animations in a platform-agnostic manner, without requiring a specific framework or an Ionic app.
创建高效的动画可能具有挑战性,因为开发者受限于设备可用的库和硬件资源。此外,许多动画库使用由 JavaScript 驱动的方法,这可能会降低动画的可扩展性并占用 CPU 时间。
🌐 Creating efficient animations can be challenging, as developers are limited by the available libraries and hardware resources of the device. Moreover, many animation libraries use a JavaScript-driven approach, which can reduce the scalability of animations and use up CPU time.
另一方面,Ionic 动画使用的是 Web Animations API,它将所有动画的计算和运行都交给浏览器处理。这种方法允许浏览器优化动画并确保其平滑执行。在 Web Animations 不被支持的情况下,Ionic 动画将回退到 CSS 动画,其性能差异应该可以忽略不计。
🌐 Ionic Animations, on the other hand, uses the Web Animations API, which offloads all the computation and running of animations to the browser. This approach allows the browser to optimize the animations and ensure their smooth execution. In cases where Web Animations are not supported, Ionic Animations will fall back to CSS Animations, which should have a negligible difference in performance.
安装
🌐 Installation
- JavaScript
- TypeScript
- Angular
- Angular (Standalone)
- React
- Vue
Developers using Ionic Core and JavaScript should install the latest version of @ionic/core.
import { createAnimation } from 'https://cdn.jsdelivr.net/npm/@ionic/core@latest/dist/esm/index.mjs';
...
const animation = createAnimation()
.addElement(myElementRef)
.duration(1000)
.fromTo('opacity', '1', '0.5');
}
Developers using Ionic Core and TypeScript should install the latest version of @ionic/core.
import { createAnimation, Animation } from '@ionic/core';
...
const animation: Animation = createAnimation('')
.addElement(myElementRef)
.duration(1000)
.fromTo('opacity', '1', '0.5');
}
Developers using Angular should install the latest version of @ionic/angular. Animations can be created via the AnimationController dependency injection.
import { Animation, AnimationController } from '@ionic/angular';
...
constructor(private animationCtrl: AnimationController) {
const animation: Animation = this.animationCtrl.create()
.addElement(myElementRef)
.duration(1000)
.fromTo('opacity', '1', '0.5');
}
Developers using Angular should install the latest version of @ionic/angular. Animations can be created via the AnimationController dependency injection.
import { Animation, AnimationController } from '@ionic/angular/standalone';
...
constructor(private animationCtrl: AnimationController) {
const animation: Animation = this.animationCtrl.create()
.addElement(myElementRef)
.duration(1000)
.fromTo('opacity', '1', '0.5');
}
Developers using React should install the latest version of @ionic/react. React wrappers are in beta. Please report any issues on GitHub!
import { CreateAnimation, Animation } from '@ionic/react';
...
<CreateAnimation
duration={1000}
fromTo={{
property: 'opacity',
fromValue: '1',
toValue: '0.5'
}}
>
...
</CreateAnimation>
Developers using Ionic Vue should install the latest version of @ionic/vue.
import { createAnimation } from '@ionic/vue';
import { ref } from 'vue';
...
const myElementRef = ref();
...
const animation = createAnimation()
.addElement(myElementRef.value)
.duration(1000)
.fromTo('opacity', '1', '0.5');
}
基本动画
🌐 Basic Animations
在下面的示例中,创建了一个动画,该动画会改变 ion-card 元素的不透明度,并沿 X 轴从左向右移动。该动画将无限次运行,每次动画的持续时间为 1500 毫秒。
🌐 In the example below, an animation that changes the opacity on the ion-card element and moves it from left to right along the X axis has been created. This animation will run an infinite number of times, and each iteration of the animation will last 1500ms.
默认情况下,所有 Ionic 动画都会暂停,直到调用 play 方法。
🌐 By default, all Ionic Animations are paused until the play method is called.
关键帧动画
🌐 Keyframe Animations
Ionic 动画允许你使用关键帧控制动画中的中间步骤。这里可以使用任何有效的 CSS 属性,甚至可以使用 CSS 变量作为值。
🌐 Ionic Animations allows you to control the intermediate steps in an animation using keyframes. Any valid CSS property can be used here, and you can even use CSS Variables as values.
在编写关键帧时,连字符的 CSS 属性应使用驼峰命名法。例如,border-radius 应写作 borderRadius。这同样适用于 fromTo()、from(), 和 to() 方法。
🌐 Hyphenated CSS properties should be written using camel case when writing keyframes. For example, border-radius should be written as borderRadius. This also applies to the fromTo(), from(), and to() methods.
在上面的示例中,卡片元素将从其初始宽度过渡到由 --width 变量定义的宽度,然后再过渡到最终的宽度。
🌐 In the example above, the card element will transition from its initial width, to a width defined by the --width variable, and then transition on to the final width.
每个关键帧对象都包含一个 offset 属性。offset 是介于 0 和 1 之间的值,用于定义关键帧步骤。偏移值必须按升序排列,并且不能重复。
🌐 Each keyframe object contains an offset property. offset is a value between 0 and 1 that defines the keyframe step. Offset values must go in ascending order and cannot repeat.
分组动画
🌐 Grouped Animations
多个元素可以同时进行动画,并通过单个父动画对象进行控制。子动画会继承持续时间、缓动和重复次数等属性,除非另有指定。父动画的 onFinish 回调在所有子动画完成之前不会被调用。
🌐 Multiple elements can be animated at the same time and controlled via a single parent animation object. Child animations inherit properties such as duration, easing, and iterations unless otherwise specified. A parent animation's onFinish callback will not be called until all child animations have completed.
此示例显示了由单个父动画控制的3个子动画。动画cardA和cardB继承了父动画2000毫秒的持续时间,但动画cardC的持续时间为5000毫秒,因为它是显式设置的。
🌐 This example shows 3 child animations controlled by a single parent animation. Animations cardA and cardB inherit the parent animation's duration of 2000ms, but animation cardC has a duration of 5000ms since it was explicitly set.
钩子之前和之后
🌐 Before and After Hooks
Ionic 动画提供了钩子,允许你在动画运行之前和动画完成之后修改一个元素。这些钩子可用于执行 DOM 读取和写入操作,以及添加或删除类和内联样式。
🌐 Ionic Animations provides hooks that let you alter an element before an animation runs and after an animation completes. These hooks can be used to perform DOM reads and writes as well as add or remove classes and inline styles.
这个示例设置了一个内联滤镜,该滤镜在动画开始前通过 75% 反转卡片的背景颜色。动画结束后,元素的盒阴影被设置为 rgba(255, 0, 50, 0.4) 0px 4px 16px 6px,一个红色的光晕,同时清除了内联滤镜。必须停止动画才能移除盒阴影,并再次使用滤镜播放动画。
🌐 This example sets an inline filter which inverts the background color of the card by 75% prior to the animation starting. Once the animation finishes, the box shadow on the element is set to rgba(255, 0, 50, 0.4) 0px 4px 16px 6px, a red glow, and the inline filter is cleared. The animation must be stopped in order to remove the box shadow and play it with the filter again.
请参见 Methods 获取完整的钩子列表。
🌐 See Methods for a complete list of hooks.
连锁动画
🌐 Chained Animations
动画可以串联,以便一个接一个地运行。play 方法返回一个 Promise,当动画完成时该 Promise 会被解决。
🌐 Animations can be chained to run one after the other. The play method returns a Promise that resolves when the animation has completed.
手势动画
🌐 Gesture Animations
Ionic 动画使开发者能够通过与 Ionic 手势 无缝集成来创建强大的基于手势的动画。
🌐 Ionic Animations gives developers the ability to create powerful gesture-based animations by integrating seamlessly with Ionic Gestures.
在以下示例中,我们正在创建一条轨道,可以沿着它拖动卡片元素。我们的 animation 对象将负责将卡片元素向左或向右移动,而我们的 gesture 对象将指示 animation 对象移动的方向。
🌐 In the following example we are creating a track along which we can drag the card element. Our animation object will take care of moving the card element either left or right, and our gesture object will instruct the animation object which direction to move in.
基于偏好的动画
🌐 Preference-Based Animations
开发者还可以使用 CSS 变量根据用户偏好(如 prefers-reduced-motion 和 prefers-color-scheme)定制他们的动画。
🌐 Developers can also tailor their animations to user preferences such as prefers-reduced-motion and prefers-color-scheme using CSS Variables.
当第一次创建动画时,这种方法在所有受支持的浏览器中都有效。大多数浏览器还能够在 CSS 变量变化时动态更新关键帧动画。
🌐 This method works in all supported browsers when creating animations for the first time. Most browsers are also capable of dynamically updating keyframe animations as the CSS Variables change.
Safari 当前不支持动态更新关键帧动画。对于需要在 Safari 中支持此类功能的开发者,他们可以使用 MediaQueryList.addListener()。
🌐 Safari does not currently support dynamically updating keyframe animations. For developers who need this kind of support in Safari, they can use MediaQueryList.addListener().
覆盖 Ionic 组件动画
🌐 Overriding Ionic Component Animations
某些 Ionic 组件允许开发者提供自定义动画。所有动画都可以作为组件的属性提供,或者通过全局配置设置。
🌐 Certain Ionic components allow developers to provide custom animations. All animations are provided as either properties on the component or are set via a global config.
模态
🌐 Modals
性能考虑因素
🌐 Performance Considerations
CSS 和网页动画通常在合成线程上处理。这不同于执行布局、绘制、样式和你的 JavaScript 的主线程。建议你优先使用可以在合成线程上处理的属性,以获得最佳动画性能。
🌐 CSS and Web Animations are usually handled on the compositor thread. This is different than the main thread where layout, painting, styling, and your JavaScript is executed. It is recommended that you prefer using properties that can be handled on the compositor thread for optimal animation performance.
像 height 和 width 这样的属性动画会导致额外的布局和重绘,这可能会引起卡顿并降低动画性能。另一方面,像 transform 和 opacity 这样的属性动画可以被浏览器高度优化,通常不会引起太多卡顿。
🌐 Animating properties such as height and width cause additional layouts and paints which can cause jank and degrade animation performance. On the other hand, animating properties such as transform and opacity are highly optimizable by the browser and typically do not cause much jank.
有关哪些 CSS 属性会导致布局或绘制发生的信息,请参阅 CSS Triggers。
🌐 For information on which CSS properties cause layouts or paints to occur, see CSS Triggers.
调 试
🌐 Debugging
对于在 Chrome 中调试动画,有一篇很棒的博客文章介绍了如何使用 Chrome DevTools 检查动画:https://developers.google.com/web/tools/chrome-devtools/inspect-styles/animations。
🌐 For debugging animations in Chrome, there is a great blog post about inspecting animations using the Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools/inspect-styles/animations.
还建议为你的动画分配唯一的标识符。这些标识符将显示在 Chrome 的动画检查器中,并应使调试更容易:
🌐 It is also recommended to assign unique identifiers to your animations. These identifiers will show up in the Animations inspector in Chrome and should make it easier to debug:
/**
* The animation for the .square element should
* show "my-animation-identifier" in Chrome DevTools.
*/
const animation = createAnimation('my-animation-identifier')
.addElement(document.querySelector('.square'))
.duration(1000)
.fromTo('opacity', '1', '0');
应用编程接口
🌐 API
本节提供了 Animation 类中可用的所有方法和属性的列表。
🌐 This section provides a list of all the methods and properties available on the Animation class.
接口
🌐 Interfaces
AnimationDirection
type AnimationDirection = 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
AnimationFill
type AnimationFill = 'auto' | 'none' | 'forwards' | 'backwards' | 'both';
AnimationBuilder
type AnimationBuilder = (baseEl: any, opts?: any) => Animation;
opts 是特定于自定义动画的附加选项。例如,表单模态进入动画包含当前断点的信息。
AnimationCallbackOptions
interface AnimationCallbackOptions {
/**
* If true, the associated callback will only be fired once.
*/
oneTimeCallback: boolean;
}
AnimationPlayOptions
interface AnimationPlayOptions {
/**
* If true, the animation will play synchronously.
* This is the equivalent of running the animation
* with a duration of 0ms.
*/
sync: boolean;
}
属性
🌐 Properties
| 名称 | 描述 |
|---|---|
childAnimations: Animation[] | 给定父动画的所有子动画。 |
elements: HTMLElement[] | 附加到动画的所有元素。 |
parentAnimation?: Animation | 给定动画对象的父动画。 |
方法
🌐 Methods
| 名称 | 描述 |
| --- | --- |
| addAnimation(animationToAdd: Animation \| Animation[]): Animation | 将一个或多个动画组合在一起,由父动画控制。 |
| addElement(el: Element \| Element[] \| Node \| Node[] \| NodeList): Animation | 向动画中添加一个或多个元素。 |
| afterAddClass(className: string \| string[]): Animation | 在动画结束后,将一个类或一组类添加到动画中的所有元素上。 |
| afterAddRead(readFn: (): void): Animation | 添加一个在动画结束后执行 DOM 读取的函数。 |
| afterAddWrite(writeFn: (): void): Animation | 添加一个在动画结束后执行 DOM 写入的函数。 |
| afterClearStyles(propertyNames: string[]): Animation | 在动画结束后,将一组属性名称添加到动画中所有元素的内联样式中以清除这些属性。 |
| afterRemoveClass(className: string \| string[]): Animation | 在动画结束后,将一个类或一组类从动画中的所有元素中移除。 |
| afterStyles(styles: { [property: string]: any }): Animation | 在动画结束后,向所有元素添加一组要应用的样式对象。 |
| beforeAddClass(className: string \| string[]): Animation | 在动画开始前,将一个类或类数组添加到动画中的所有元素。 |
| beforeAddRead(readFn: (): void): Animation | 添加一个在动画开始前执行 DOM 读取的函数。 |
| beforeAddWrite(writeFn: (): void): Animation | 添加一个在动画开始前执行 DOM 写入的函数。 |
| beforeClearStyles(propertyNames: string[]): Animation | 在动画开始之前,将一组属性名称添加到动画中,以从所有元素的内联样式中清除这些属性。 |
| beforeRemoveClass(className: string \| string[]): Animation | 在动画开始之前,将一个类或一组类添加到动画中,以从所有元素中移除这些类。 |
| beforeStyles(styles: { [property: string]: any }): Animation | 在动画开始之前,向所有元素添加要应用的样式对象。 |
| direction(direction?: AnimationDirection): Animation | 设置动画应播放的方向。 |
| delay(delay?: number): Animation | 设置动画开始的延迟时间(毫秒)。 |
| destroy(clearStyleSheets?: boolean): Animation | 销毁动画并清除所有元素、子动画和关键帧。 |
| duration(duration?: number): Animation | 设置动画的持续时间(以毫秒为单位)。 |
| easing(easing?: string): Animation | 设置动画的缓动时间(以毫秒为单位)。有关可接受的缓动值列表,请参见 缓动效果。 |
| from(property: string, value: any): Animation | 设置动画的起始样式。 |
| fromTo(property: string, fromValue: any, toValue: any): Animation | 设置动 画的开始和结束样式。 |
| fill(fill?: AnimationFill): Animation | 设置动画在执行前后如何将样式应用到其元素上。 |
| iterations(iterations: number): Animation | 设置动画循环在停止之前应播放的次数。 |
| keyframes(keyframes: any[]): Animation | 设置动画的关键帧。 |
| onFinish(callback: (didComplete: boolean, animation: Animation): void, opts?: AnimationCallbackOptions): Animation | 在动画结束时添加一个要运行的回调函数。 |
| pause(): Animation | 暂停动画。 |
| play(opts?: AnimationPlayOptions): Promise<void> | 播放动画。 |
| progressEnd(playTo?: 0 \| 1, step: number, dur?: number): Animation | 停止通过动画进行搜索。 |
| progressStart(forceLinearEasing?: boolean, step?: number): Animation | 开始通过动画进行搜索。 |
| progressStep(step: number): Animation | 搜索动画。 |
| stop(): Animation | 停止动画并将所有元素重置到初始状态。 |
| to(property: string, value: any): Animation | 设置动画的结束样式。 |