欧洲杯官网投注

Ionic Docs Docs

Native

Search docs/
Search docs/
Ionic Docs Docs
  • Structure
  • Responsive Grid
  • Global StylesheetsCSS Utilities
  • Basics
  • Platform Styles
  • CSS VariablesColorsThemesDark ModeAdvancedColor Generator
  • Overview
  • Build Your First App
    LifecycleNavigation/RoutingConfigPlatformTestingStoragePerformanceProgressive Web Apps
  • Overview
  • Quickstart
  • Build Your First App
    LifecycleNavigation/RoutingConfigPlatform UtilsProgressive Web AppsTesting
  • Overview
  • Build Your First App
  • LifecycleNavigation/Routing
  • Animations
  • Gestures
  • iOS App Store
  • Android Play StoreProgressive Web App (PWA)Electron Desktop App
  • Security
  • Debugging
  • Build ErrorsRuntime ErrorsNative ErrorsCORS Errors
  • Fundamentals
  • Cross PlatformWeb ViewWhat are PWAs?
  • How to Contribute
  • Code of Conduct
  • Glossary
  • VersioningRelease NotesGitHub Changelog
  • Support Policy
  • Browser Support
  • Migration
  • Books
  • CoursesGuidesPostsToolsVideos
    Animations
    Contents

    Overview

    Ionic Animations is a utility that allows developers to build complex animations in a platform agnostic manner. Developers do not need to be using a particular framework such as React or Angular, nor do they even need to be building an Ionic app. As long as developers have access to v5.0 or greater of Ionic Framework, they will have access to all of Ionic Animations.

    Building efficient animations can be tricky. Developers are often limited by the libraries available to them as well as the hardware that their apps run on. On top of that, many animation libraries use a JavaScript-driven approach to running animations where they handle the calculation of your animation's values at every step in arequestAnimationFrame loop. This reduces the scalability of your animations as the library is constantly computing values and using up CPU time.

    Ionic Animations uses the Web Animations API to build and run your animations. In doing this, we offload all work required to compute and run your animations to the browser. As a result, this allows the browser to make any optimizations it needs and ensures your animations run as smoothly as possible. While most browsers support a basic implementation of Web Animations, we fallback toCSS Animations欧洲杯官网投注 for browsers that do not support Web Animations. The performance difference in switching between these two should typically be negligible.

    Installation

    Developers using Ionic Core and JavaScript should install the latest version of@ionic/core.

    import { createAnimation } from 'http://cdn.jsdelivr.net/npm/@ionic/core@latest/dist/esm/index.mjs';...const animation = createAnimation()  .addElement(myElementRef)  .duration(1000)  .fromTo('opacity', '1', '0.5');}
    CopyCopied

    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');}
    CopyCopied

    Developers using Angular should install the latest version of@ionic/angular. Animations can be created via theAnimationController 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');}
    CopyCopied

    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>
    CopyCopied

    Basic Animations

    Usage

    createAnimation()  .addElement(document.querySelector('.square'))  .duration(1500)  .iterations(Infinity)  .fromTo('transform', 'translateX(0px)', 'translateX(100px)')  .fromTo('opacity', '1', '0.2');
    CopyCopied
    this.animationCtrl.create()  .addElement(document.querySelector('.square'))  .duration(1500)  .iterations(Infinity)  .fromTo('transform', 'translateX(0px)', 'translateX(100px)')  .fromTo('opacity', '1', '0.2');
    CopyCopied
    <CreateAnimation  duration={1500}  iterations={Infinity}  fromTo={[    { property: 'transform', fromValue: 'translateX(0px)', toValue: 'translateX(100px)' },    { property: 'opacity', fromValue: '1', toValue: '0.2' }  ]}>  ...</CreateAnimation>
    CopyCopied

    In the example above, an animation that changes the opacity on the.square欧洲杯官网投注 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.

    By default, all Ionic Animations are paused until the play method is called.

    Keyframe Animations

    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.

    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(), andto() methods.

    Usage

    createAnimation()  .addElement(document.querySelector('.square'))  .duration(3000)  .iterations(Infinity)  .keyframes([    { offset: 0, background: 'red' },    { offset: 0.72, background: 'var(--background)' },    { offset: 1, background: 'green' }  ]);
    CopyCopied
    this.animationCtrl.create()  .addElement(this.square.nativeElement)  .duration(3000)  .iterations(Infinity)  .keyframes([    { offset: 0, background: 'red' },    { offset: 0.72, background: 'var(--background)' },    { offset: 1, background: 'green' }  ]);
    CopyCopied
    <CreateAnimation  duration={3000}  iterations={Infinity}  keyframes={[    { offset: 0, background: 'red' },    { offset: 0.72, background: 'var(--background)' },    { offset: 1, background: 'green' }  ]}>...</CreateAnimation>
    CopyCopied

    In the example above, the.square element will transition from a red background color, to a background color defined by the--background variable, and then transition on to a green background color.

    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

    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'sonFinish欧洲杯官网投注 callback will not be called until all child animations have completed.

    Usage

    const squareA = createAnimation()  .addElement(document.querySelector('.square-a'))  .keyframes([    { offset: 0, transform: 'scale(1) rotate(0)' },    { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },    { offset: 1, transform: 'scale(1) rotate(45deg)' }  ]);const squareB = createAnimation()  .addElement(document.querySelector('.square-b'))  .keyframes([    { offset: 0, transform: 'scale(1))', opacity: '1' },    { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },    { offset: 1, transform: 'scale(1)', opacity: '1' }  ]);const squareC = createAnimation()  .addElement(document.querySelector('.square-c'))  .duration(5000)  .keyframes([    { offset: 0, transform: 'scale(1))', opacity: '0.5' },    { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },    { offset: 1, transform: 'scale(1)', opacity: '0.5' }  ]);const parent = createAnimation()  .duration(2000)  .iterations(Infinity)  .addAnimation([squareA, squareB, squareC]);
    CopyCopied
    const squareA = this.animationCtrl.create()  .addElement(this.squareA.nativeElement)  .keyframes([    { offset: 0, transform: 'scale(1) rotate(0)' },    { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },    { offset: 1, transform: 'scale(1) rotate(45deg)' }  ]);const squareB = this.animationCtrl.create()  .addElement(this.squareB.nativeElement)  .keyframes([    { offset: 0, transform: 'scale(1))', opacity: '1' },    { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },    { offset: 1, transform: 'scale(1)', opacity: '1' }  ]);const squareC = this.animationCtrl.create()  .addElement(this.squareC.nativeElement)  .duration(5000)  .keyframes([    { offset: 0, transform: 'scale(1))', opacity: '0.5' },    { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },    { offset: 1, transform: 'scale(1)', opacity: '0.5' }  ]);const parent = this.animationCtrl.create()  .duration(2000)  .iterations(Infinity)  .addAnimation([squareA, squareB, squareC]);
    CopyCopied
    private parentRef: React.RefObject<CreateAnimation> = React.createRef();private squareARef: React.RefObject<CreateAnimation> = React.createRef();private squareBRef: React.RefObject<CreateAnimation> = React.createRef();private squareCRef: React.RefObject<CreateAnimation> = React.createRef();...componentDidMount() {  const parent = this.parentRef.current!.animation;  const squareA = this.squareARef.current!.animation;  const squareB = this.squareBRef.current!.animation;  const squareC = this.squareCRef.current!.animation;  parent.addAnimation([squareA, squareB, squareC]);}render() {  return (    <>      <CreateAnimation        ref={this.parentRef}        duration={2000}        iterations={Infinity}      ></CreateAnimation>      <CreateAnimation        ref={this.squareARef}        keyframes={[          { offset: 0, transform: 'scale(1) rotate(0)' },          { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },          { offset: 1, transform: 'scale(1) rotate(0deg)' }        ]}      >        <div className="square"></div>      </CreateAnimation>      <CreateAnimation        ref={this.squareBRef}        keyframes={[          { offset: 0, transform: 'scale(1)', opacity: '1' },          { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },          { offset: 1, transform: 'scale(1)', opacity: '1' }        ]}      >        <div className="square"></div>      </CreateAnimation>      <CreateAnimation        ref={this.squareCRef}        duration={5000}        keyframes={[          { offset: 0, transform: 'scale(1)', opacity: '0.5' },          { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },          { offset: 1, transform: 'scale(1)', opacity: '0.5' }        ]}      >        <div className="square"></div>      </CreateAnimation>    </>  )}
    CopyCopied

    This example shows 3 child animations controlled by a single parent animation. AnimationssquareA andsquareB inherit the parent animation's duration of 2000ms, but animationsquareC has a duration of 5000ms since it was explicitly set.

    Before and After Hooks

    欧洲杯官网投注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.

    Usage

    createAnimation()  .addElement(document.querySelector('.square'))  .duration(2000)  .beforeStyles({    opacity: 0.2  })  .afterStyles({    background: 'rgba(0, 255, 0, 0.5)'  })  .afterClearStyles(['opacity'])  .keyframes([    { offset: 0, transform: 'scale(1)' },    { offset: 0.5, transform: 'scale(1.5)' },    { offset: 1, transform: 'scale(1)' }  ])
    CopyCopied
    this.animationCtrl.create()  .addElement(this.square.nativeElement)  .duration(2000)  .beforeStyles({    opacity: 0.2  })  .afterStyles({    background: 'rgba(0, 255, 0, 0.5)'  })  .afterClearStyles(['opacity'])  .keyframes([    { offset: 0, transform: 'scale(1)' },    { offset: 0.5, transform: 'scale(1.5)' },    { offset: 1, transform: 'scale(1)' }  ])
    CopyCopied
    <CreateAnimation  duration={2000}  beforeStyles={{    opacity: 0.2  }}  afterStyles={{    background: 'rgba(0, 255, 0, 0.5)'  }}  afterClearStyles={['opacity']}  keyframes={[    { offset: 0, transform: 'scale(1)' },    { offset: 0.5, transform: 'scale(1.5)' },    { offset: 1, transform: 'scale(1)' }  ]}>  ...</CreateAnimation>
    CopyCopied

    In this example, an inline opacity of 0.2 is set on the.square element prior to the animation starting. Once the animation finishes, the background color of the element is set torgba(0, 255, 0, 0.5), and the inline opacity is cleared.

    See Methods for a complete list of hooks.

    Chained Animations

    Animations can be chained to run one after the other. Theplay欧洲杯官网投注 method returns a Promise that resolves when the animation has completed.

    Usage

    const squareA = createAnimation()  .addElement(document.querySelector('.square-a'))  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1) rotate(0)' },    { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },    { offset: 1, transform: 'scale(1) rotate(0)' }  ]);const squareB = createAnimation()  .addElement(document.querySelector('.square-b'))  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1)', opacity: '1' },    { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },    { offset: 1, transform: 'scale(1)', opacity: '1' }  ]);const squareC = createAnimation()  .addElement(document.querySelector('.square-c'))  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1)', opacity: '0.5' },    { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },    { offset: 1, transform: 'scale(1)', opacity: '0.5' }  ]);await squareA.play();await squareB.play();await squareC.play();
    CopyCopied
    const squareA = this.animationCtrl.create()  .addElement(this.squareA.nativeElement)  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1) rotate(0)' },    { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },    { offset: 1, transform: 'scale(1) rotate(0)' }  ]);const squareB = this.animationCtrl.create()  .addElement(this.squareB.nativeElement)  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1)', opacity: '1' },    { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },    { offset: 1, transform: 'scale(1)', opacity: '1' }  ]);const squareC = this.animationCtrl.create()  .addElement(this.squareC.nativeElement)  .fill('none')  .duration(1000)  .keyframes([    { offset: 0, transform: 'scale(1)', opacity: '0.5' },    { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },    { offset: 1, transform: 'scale(1)', opacity: '0.5' }  ]);await squareA.play();await squareB.play();await squareC.play();
    CopyCopied
    private squareARef: React.RefObject<CreateAnimation> = React.createRef();private squareBRef: React.RefObject<CreateAnimation> = React.createRef();private squareCRef: React.RefObject<CreateAnimation> = React.createRef();...async componentDidMount() {  const squareA = this.squareARef.current!.animation;  const squareB = this.squareBRef.current!.animation;  const squareC = this.squareCRef.current!.animation;  await squareA.play();  await squareB.play();  await squareC.play();}render() {  return (    <>      <CreateAnimation        ref={this.squareARef}        fill="none"        duration={1000}        keyframes={[          { offset: 0, transform: 'scale(1) rotate(0)' },          { offset: 0.5, transform: 'scale(1.2) rotate(45deg)' },          { offset: 1, transform: 'scale(1) rotate(0deg)' }        ]}      >        <div className="square"></div>      </CreateAnimation>      <CreateAnimation        ref={this.squareBRef}        fill="none"        duration={1000}        keyframes={[          { offset: 0, transform: 'scale(1)', opacity: '1' },          { offset: 0.5, transform: 'scale(1.2)', opacity: '0.3' },          { offset: 1, transform: 'scale(1)', opacity: '1' }        ]}      >        <div className="square"></div>      </CreateAnimation>      <CreateAnimation        ref={this.squareCRef}        fill="none"        duration={1000}        keyframes={[          { offset: 0, transform: 'scale(1)', opacity: '0.5' },          { offset: 0.5, transform: 'scale(0.8)', opacity: '1' },          { offset: 1, transform: 'scale(1)', opacity: '0.5' }        ]}      >        <div className="square"></div>      </CreateAnimation>    </>  )}
    CopyCopied

    Gesture Animations

    Ionic Animations gives developers the ability to create powerful gesture-based animations by integrating seamlessly withIonic Gestures.

    Usage

    let initialStep = 0;let started = false;const square = document.querySelector('.square');const MAX_TRANSLATE = 400;const animation = createAnimation()  .addElement(square)  .duration(1000)  .fromTo('transform', 'translateX(0)', `translateX(${MAX_TRANSLATE}px)`);const gesture = createGesture({  el: square,  threshold: 0,  gestureName: 'square-drag',  onMove: ev: onMove(ev),  onEnd: ev: onEnd(ev)})gesture.enable(true);const onMove = (ev): {  if (!started) {    animation.progressStart();    started = true;  }  animation.progressStep(getStep(ev));}const onEnd = (ev): {  if (!started) { return; }  gesture.enable(false);  const step = getStep(ev);  const shouldComplete = step > 0.5;  animation    .progressEnd((shouldComplete) ? 1 : 0, step)    .onFinish((): { gesture.enable(true); });  initialStep = (shouldComplete) ? MAX_TRANSLATE : 0;  started = false;}const clamp = (min, n, max): {  return Math.max(min, Math.min(n, max));};const getStep = (ev): {  const delta = initialStep + ev.deltaX;  return clamp(0, delta / MAX_TRANSLATE, 1);}
    CopyCopied
    private animation?: Animation;private gesture?: Gesture;private started: boolean = false;private initialStep: number = 0;private MAX_TRANSLATE: number = 400;ngOnInit() {      this.animation = this.animationCtrl.create()    .addElement(this.square.nativeElement)    .duration(1000)    .fromTo('transform', 'translateX(0)', `translateX(${this.MAX_TRANSLATE}px)`);  this.gesture = this.gestureCtrl.create({    el: this.square.nativeElement,    threshold: 0,    gestureName: 'square-drag',    onMove: ev: this.onMove(ev),    onEnd: ev: this.onEnd(ev)  })  this.gesture.enable(true);}private onMove(ev) {  if (!started) {    this.animation.progressStart();    this.started = true;  }  this.animation.progressStep(this.getStep(ev));}private onEnd(ev) {  if (!this.started) { return; }  this.gesture.enable(false);  const step = this.getStep(ev);  const shouldComplete = step > 0.5;  this.animation    .progressEnd((shouldComplete) ? 1 : 0, step)    .onFinish((): { this.gesture.enable(true); });  this.initialStep = (shouldComplete) ? this.MAX_TRANSLATE : 0;  this.started = false;}private clamp(min, n, max) {  return Math.max(min, Math.min(n, max));}private getStep(ev) {  const delta = this.initialStep + ev.deltaX;  return this.clamp(0, delta / this.MAX_TRANSLATE, 1);}
    CopyCopied
    import { createGesture, CreateAnimation, Gesture, GestureDetail } from '@ionic/react';import React from 'react';const MAX_TRANSLATE = 400;class MyComponent extends React.Component<{}, any> {  private animation: React.RefObject<CreateAnimation> = React.createRef();  private gesture?: Gesture;  private started: boolean = false;  private initialStep: number = 0;  constructor(props: any) {    super(props);    this.state = {      progressStart: undefined,      progressStep: undefined,      progressEnd: undefined,      onFinish: undefined    };  }  componentDidMount() {    const square = Array.from(this.animation.current!.nodes.values())[0];    this.gesture = createGesture({      el: square,      gestureName: 'square-drag',      threshold: 0,      onMove: ev => this.onMove(ev),      onEnd: ev => this.onEnd(ev)    });    this.gesture.enable(true);  }  private onMove(ev: GestureDetail) {        if (!this.started) {      this.setState({        ...this.state,        progressStart: { forceLinearEasing: true }      });      this.started = true;    }    this.setState({      ...this.state,      progressStep: { step: this.getStep(ev) }    });  }  private onEnd(ev: GestureDetail) {    if (!this.started) { return; }    this.gesture!.enable(false);    const step = this.getStep(ev);    const shouldComplete = step > 0.5;    this.setState({      ...this.state,      progressEnd: { playTo: (shouldComplete) ? 1 : 0, step },      onFinish: { callback: () => {        this.gesture!.enable(true);        this.setState({          progressStart: undefined,          progressStep: undefined,          progressEnd: undefined        })      }, opts: { oneTimeCallback: true }}    });    this.initialStep = (shouldComplete) ? MAX_TRANSLATE : 0;    this.started = false;  }  private getStep(ev: GestureDetail) {    const delta = this.initialStep + ev.deltaX;    return this.clamp(0, delta / MAX_TRANSLATE, 1);  }  private clamp(min: number, n: number, max: number) {    return Math.max(min, Math.min(n, max));  }  render() {    return (      <>        <div className="track">          <CreateAnimation            ref={this.animation}            duration={1000}            progressStart={this.state.progressStart}            progressStep={this.state.progressStep}            progressEnd={this.state.progressEnd}            onFinish={this.state.onFinish}            fromTo={{              property: 'transform',              fromValue: 'translateX(0)',              toValue: `translateX(${MAX_TRANSLATE}px)`          }}>            <div className="square"></div>          </CreateAnimation>        </div>      </>    );  }}
    CopyCopied

    In this example we are creating a track along which we can drag the.square element. Ouranimation object will take care of moving the.square element either left or right, and ourgesture object will instruct theanimation欧洲杯官网投注 object which direction to move in.

    Preference-Based Animations

    Developers can also tailor their animations to user preferences such asprefers-reduced-motion andprefers-color-scheme using CSS Variables.

    Usage

    .square {  width: 100px;  height: 100px;  opacity: 0.5;  background: blue;  margin: 10px;  --background: red;}@media (prefers-color-scheme: dark) {  .square {    --background: green;  }}
    CopyCopied
    createAnimation()   .addElement(document.querySelector('.square'))   .duration(1500)   .iterations(Infinity)   .direction('alternate')   .fromTo('background', 'blue', 'var(--background)');
    CopyCopied
    this.animationCtrl.create()   .addElement(this.square.nativeElement)   .duration(1500)   .iterations(Infinity)   .direction('alternate')   .fromTo('background', 'blue', 'var(--background)');
    CopyCopied
    <CreateAnimation  duration={1500}  iterations={Infinity}  direction='alternate'  fromTo={{    property: 'background',    fromValue: 'blue',    toValue: 'var(--background)'  }}>  <div className="square"></div></CreateAnimation>
    CopyCopied

    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 does not currently support dynamically updating keyframe animations. For developers who need this kind of support in Safari, they can useMediaQueryList.addListener().

    Overriding Ionic Component Animations

    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

    customElements.define('modal-page', class extends HTMLElement {  connectedCallback() {    this.innerHTML = `      <ion-header>        <ion-toolbar>          <ion-title>Modal Header</ion-title>        </ion-toolbar>      </ion-header>      <ion-content class="ion-padding">        Modal Content      </ion-content>    `;  }});function presentModal() {  const enterAnimation = (baseEl: any) => {    const backdropAnimation = createAnimation()      .addElement(baseEl.querySelector('ion-backdrop')!)      .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');    const wrapperAnimation = createAnimation()      .addElement(baseEl.querySelector('.modal-wrapper')!)      .keyframes([        { offset: 0, opacity: '0', transform: 'scale(0)' },        { offset: 1, opacity: '0.99', transform: 'scale(1)' }      ]);    return createAnimation()      .addElement(baseEl)      .easing('ease-out')      .duration(500)      .addAnimation([backdropAnimation, wrapperAnimation]);  }  const leaveAnimation = (baseEl: any) => {    return enterAnimation(baseEl).direction('reverse');  }  // create the modal with the `modal-page` component  const modalElement = document.createElement('ion-modal');  modalElement.component = 'modal-page';  modalElement.enterAnimation = enterAnimation;  modalElement.leaveAnimation = leaveAnimation;  // present the modal  document.body.appendChild(modalElement);  return modalElement.present();}
    CopyCopied
    import { Component } from '@angular/core';import { ModalController, AnimationController } from '@ionic/angular';import { ModalPage } from '../modal/modal.page';@Component({  selector: 'modal-example',  templateUrl: 'modal-example.html',  styleUrls: ['./modal-example.css']})export class ModalExample {  constructor(public modalController: ModalController,              public animationCtrl: AnimationController) { }  async presentModal() {    const enterAnimation = (baseEl: any) => {      const backdropAnimation = this.animationCtrl.create()        .addElement(baseEl.querySelector('ion-backdrop')!)        .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');      const wrapperAnimation = this.animationCtrl.create()        .addElement(baseEl.querySelector('.modal-wrapper')!)        .keyframes([          { offset: 0, opacity: '0', transform: 'scale(0)' },          { offset: 1, opacity: '0.99', transform: 'scale(1)' }        ]);      return this.animationCtrl.create()        .addElement(baseEl)        .easing('ease-out')        .duration(500)        .addAnimation([backdropAnimation, wrapperAnimation]);    }    const leaveAnimation = (baseEl: any) => {      return enterAnimation(baseEl).direction('reverse');    }    const modal = await this.modalController.create({      component: ModalPage,      enterAnimation,      leaveAnimation    });    return await modal.present();  }}
    CopyCopied
    import React, { useState } from 'react';import { CreateAnimation, IonModal, IonButton, IonContent } from '@ionic/react';export const ModalExample: React.FC = () => {  const [showModal, setShowModal] = useState(false);  const enterAnimation = (baseEl: any) => {    const backdropAnimation = createAnimation()      .addElement(baseEl.querySelector('ion-backdrop')!)      .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');    const wrapperAnimation = createAnimation()      .addElement(baseEl.querySelector('.modal-wrapper')!)      .keyframes([        { offset: 0, opacity: '0', transform: 'scale(0)' },        { offset: 1, opacity: '0.99', transform: 'scale(1)' }      ]);    return createAnimation()      .addElement(baseEl)      .easing('ease-out')      .duration(500)      .addAnimation([backdropAnimation, wrapperAnimation]);  }  const leaveAnimation = (baseEl: any) => {    return enterAnimation(baseEl).direction('reverse');  }  return (    <IonContent>      <IonModal isOpen={showModal} enterAnimation={enterAnimation} leaveAnimation={leaveAnimation}>        <p>This is modal content</p>        <IonButton onClick={() => setShowModal(false)}>Close Modal</IonButton>      </IonModal>      <IonButton onClick={() => setShowModal(true)}>Show Modal</IonButton>    </IonContent>  );};
    CopyCopied

    Performance Considerations

    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.

    Animating properties such as height andwidth cause additional layouts and paints which can cause jank and degrade animation performance. On the other hand, animating properties such astransform and opacity欧洲杯官网投注 are highly optimizable by the browser and typically do not cause much jank.

    For information on which CSS properties cause layouts or paints to occur, seeCSS Triggers.

    Debugging

    For debugging animations in Chrome, there is a great blog post about inspecting animations using the Chrome DevTools:http://developers.google.com/web/tools/chrome-devtools/inspect-styles/animations.

    欧洲杯官网投注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');
    CopyCopied
    Browser Support
    Browser/PlatformSupported Versions
    Chrome43+
    Safari9+
    Firefox32+
    IE/Edge11+
    Opera30+
    iOS9+
    Android5+
    Due to a bug in Safari versions 9-11, stepping through animations viaprogressStep is not supported. This is supported on Safari 12+.

    Types

    NameValue
    AnimationDirection'normal' | 'reverse' | 'alternate' | 'alternate-reverse'
    AnimationFill 'auto' | 'none' | 'forwards' | 'backwards' | 'both'

    Interfaces

    interface AnimationCallbackOptions {  /**   * If true, the associated callback will only be fired once.   */  oneTimeCallback: boolean;}interface AnimationPlayOptions {  /**   * If true, the animation will play synchronously.    * This is the equivalent of running the animation   * with a duration of 0ms.   */   sync: boolean;}
    CopyCopied
    Properties All elements attached to an animation.The parent animation of a given animation object.
    NameDescription
    childAnimations: Animation[]All child animations of a given parent animation.
    elements: HTMLElement[]
    parentAnimation?: Animation

    Methods

    NameDescription
    addAnimation(animationToAdd: Animation | Animation[]): AnimationGroup one or more animations together to be controlled by a parent animation.
    addElement(el: Element | Element[] | Node | Node[] | NodeList): AnimationAdd one or more elements to the animation.
    afterAddClass(className: string | string[]): AnimationAdd a class or array of classes to be added to all elements in an animation after the animation ends.
    afterAddRead(readFn: (): void): AnimationAdd a function that performs a DOM read to be run after the animation ends.
    afterAddWrite(writeFn: (): void): AnimationAdd a function that performs a DOM write to be run after the animation ends.
    afterClearStyles(propertyNames: string[]): AnimationAdd an array of property names to be cleared from the inline styles on all elements in an animation after the animation ends.
    afterRemoveClass(className: string | string[]): AnimationAdd a class or an array of classes to be removed from all elements in an animation after the animation ends.
    afterStyles(styles: { [property: string]: any }): AnimationAdd an object of styles to be applied to all elements in an animation after the animation ends.
    beforeAddClass(className: string | string[]): AnimationAdd a class or array of classes to be added to all elements in an animation before the animation starts.
    beforeAddRead(readFn: (): void): AnimationAdd a function that performs a DOM read to be run before the animation starts.
    beforeAddWrite(writeFn: (): void): AnimationAdd a function that performs a DOM write to be run before the animation starts.
    beforeClearStyles(propertyNames: string[]): AnimationAdd an array of property names to be cleared from the inline styles on all elements in an animation before the animation starts.
    beforeRemoveClass(className: string | string[]): AnimationAdd a class or an array of classes to be removed from all elements in an animation before the animation starts.
    beforeStyles(styles: { [property: string]: any }): AnimationAdd an object of styles to be applied to all elements in an animation before the animation starts.
    direction(direction?: AnimationDirection): AnimationSet the direction the animation should play in.
    delay(delay?: number): AnimationSet the delay for the start of the animation in milliseconds.
    destroy(clearStyleSheets?: boolean): AnimationDestroy the animation and clear all elements, child animations, and keyframes.
    duration(duration?: number): AnimationSet the duration of the animation in milliseconds.
    easing(easing?: string): AnimationSet the easing of the animation in milliseconds. See Easing Effects for a list of accepted easing values.
    from(property: string, value: any): AnimationSet the start styles of the animation.
    fromTo(property: string, fromValue: any, toValue: any): AnimationSet the start and end styles of the animation.
    fill(fill?: AnimationFill): AnimationSet how the animation applies styles to its elements before and after the animation's execution.
    iterations(iterations: number): AnimationSet the number of times the animation cycle should be played before stopping.
    keyframes(keyframes: any[]): AnimationSet the keyframes for an animation.
    onFinish(callback: (didComplete: boolean, animation: Animation): void, opts?: AnimationCallbackOptions): AnimationAdd a callback to be run upon the animation ending.
    pause(): Animation Pause the animation.
    play(opts?: AnimationPlayOptions): Promise<void>Play the animation.
    progressEnd(playTo?: 0 | 1, step: number, dur?: number): AnimationStop seeking through an animation.
    progressStart(forceLinearEasing: boolean, step?: number): AnimationBegin seeking through an animation.
    progressStep(step: number): AnimationSeek through an animation.
    stop(): AnimationStop the animation and reset all elements to their initial state.
    to(property: string, value: any): AnimationSet the end styles of the animation.
    Next
    Config