{"id":3553,"date":"2020-12-16T16:18:12","date_gmt":"2020-12-16T16:18:12","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=3553"},"modified":"2020-12-16T16:18:12","modified_gmt":"2020-12-16T16:18:12","slug":"building-interactive-ionic-apps-with-gestures-and-animations","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations","title":{"rendered":"Building Interactive Ionic Apps with Gestures and Animations"},"content":{"rendered":"<blockquote><p>\n  This is a guest post from Simon Grimm, Ionic Developer Expert and educator at <a href=\"https:\/\/ionicacademy.com\/\">the Ionic Academy<\/a>. Simon also created the <a href=\"https:\/\/devdactic.com\/practical-ionic\/\">Practical Ionic<\/a> book, a guide to building real world Ionic applications with Capacitor and Firebase.\n<\/p><\/blockquote>\n<p>Since Ionic 5 we got access to a great <a href=\"https:\/\/ionicframework.com\/docs\/utilities\/animations\">Animations<\/a> and <a href=\"https:\/\/ionicframework.com\/docs\/utilities\/gestures\">Gestures<\/a> utility API, which can help to add both simple interactive elements as well as complex gestures to your Ionic app.<\/p>\n<p>In this tutorial we will go through different examples to spice up our Ionic app with animations and add gestures to elements.<\/p>\n<p>Once we got the basics right, we will combine both approaches to build a custom <strong>slide to delete<\/strong> feature and finally use our own animations for Ionic page transitions!<\/p>\n<p><!--more--><\/p>\n<h2>Prerequisite<\/h2>\n<p>The coolest thing about all this upfront: You don&#8217;t need any additional package or library for everything we will implement in this tutorial!<\/p>\n<p>To follow along, simply bring up a new Ionic application and you are good to go.<\/p>\n<pre><code class=\"language-bash\">ionic start ionicInteractive blank --type=angular --capacitor\n<\/code><\/pre>\n<p>We will use Ionic Angular throughout the code snippets, but the same concepts and APIs exist for React and Vue as well.<\/p>\n<p>If you also want a bit of &#8220;behind the scenes&#8221; on why those APIs were created in the first place, travel back in time to the <a href=\"https:\/\/ionicframework.com\/blog\/introducing-ionic-animations\/\">introduction of Ionic Animations<\/a>!<\/p>\n<h2>Simple Ionic Animations<\/h2>\n<p>Enough talk, let&#8217;s write some code. We start with a simple example of animating icons and buttons, and the only thing we need is a reference to our DOM elements.<\/p>\n<p>Therefore, we create two buttons and a fab and give them a template reference so we can access them as a <code>ViewChild<\/code> later.<\/p>\n<p>Open the <strong>home\/home.page.html<\/strong> and change it to:<\/p>\n<pre><code class=\"language-html\">&lt;ion-header&gt;\n  &lt;ion-toolbar color=&quot;primary&quot;&gt;\n    &lt;ion-title&gt;\n      Ionic Interactive\n    &lt;\/ion-title&gt;\n  &lt;\/ion-toolbar&gt;\n&lt;\/ion-header&gt;\n\n&lt;ion-content class=&quot;ion-padding-top&quot;&gt;\n  &lt;ion-button expand=&quot;full&quot; (click)=&quot;startLoad()&quot;&gt;\n    Load\n    &lt;ion-icon name=&quot;reload&quot; slot=&quot;end&quot; #loadingIcon&gt;&lt;\/ion-icon&gt;\n  &lt;\/ion-button&gt;\n  &lt;ion-button expand=&quot;full&quot; (click)=&quot;addToCart()&quot; #cartBtn&gt;\n    Add to cart\n  &lt;\/ion-button&gt;\n\n  &lt;ion-fab vertical=&quot;top&quot; horizontal=&quot;end&quot; slot=&quot;fixed&quot; edge&gt;\n    &lt;ion-fab-button #cartFabBtn color=&quot;secondary&quot;&gt;\n      &lt;ion-icon name=&quot;cart&quot;&gt;&lt;\/ion-icon&gt;\n    &lt;\/ion-fab-button&gt;\n  &lt;\/ion-fab&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>Now we can access our ViewChilds, and we will add a simple dummy animation to the loading icon of the button. Imagine a case where you don&#8217;t want to cover the whole view with a loading but still show some progress.<\/p>\n<p>To create an animation, we need to handle a few things:<\/p>\n<ul>\n<li>Create a new <code>Animation<\/code> with the <code>AnimationController<\/code> and give it a name<\/li>\n<li>Add the native Element on which we want to perform the animation<\/li>\n<li>Define what the animation should do<\/li>\n<li>Call <code>play()<\/code> on the created <code>Animation<\/code><\/li>\n<\/ul>\n<p>That&#8217;s the core idea, and you can then define various elements of the animation like the <strong>duration<\/strong> (<em>how long should the animation play?<\/em>), <strong>iterations<\/strong> (<em>how often should the animation run?<\/em>) and the actual animation with keyframes or the simple <code>fromTo()<\/code> operator.<\/p>\n<p>For now, let&#8217;s simply rotate the icon 3 times, where each iteration takes 1.5 seconds.<\/p>\n<p>Therefore, open the <strong>home\/home.page.ts<\/strong> and change it to:<\/p>\n<pre><code class=\"language-ts\">import { Component, ElementRef, ViewChild } from &#039;@angular\/core&#039;;\nimport { AnimationController } from &#039;@ionic\/angular&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n  @ViewChild(&#039;loadingIcon&#039;, { read: ElementRef }) loadingIcon: ElementRef;\n  @ViewChild(&#039;cartBtn&#039;, { read: ElementRef }) cartBnt: ElementRef;\n  @ViewChild(&#039;cartFabBtn&#039;, { read: ElementRef }) cartFabBnt: ElementRef;\n\n  constructor(private animationCtrl: AnimationController) { }\n\n  startLoad() {\n    const loadingAnimation = this.animationCtrl.create(&#039;loading-animation&#039;)\n      .addElement(this.loadingIcon.nativeElement)\n      .duration(1500)\n      .iterations(3)\n      .fromTo(&#039;transform&#039;, &#039;rotate(0deg)&#039;, &#039;rotate(360deg)&#039;);\n\n    \/\/ Don&#039;t forget to start the animation!\n    loadingAnimation.play();\n  }\n}\n<\/code><\/pre>\n<p>Run your app, hit the button and you should see your first simple Ionic animation in action!<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-animation.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-animation.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<h2>Chaining Ionic Animations<\/h2>\n<p>You are not limited to just animating one element or the specific operators, you could also use keyframes like in standard CSS animations or chain different animations together!<\/p>\n<p>To create a chain, simply create two separate animations and group them together in one parent animation using <code>addAnimation()<\/code>.<\/p>\n<p>Go ahead and add a new function like this to your page:<\/p>\n<pre><code class=\"language-ts\">addToCart() {\n  const cartAnimation = this.animationCtrl.create(&#039;cart-animation&#039;)\n    .addElement(this.cartBnt.nativeElement)\n    .keyframes([\n      { offset: 0, transform: &#039;scale(1)&#039; },\n      { offset: 0.5, transform: &#039;scale(1.2)&#039; },\n      { offset: 0.8, transform: &#039;scale(0.9)&#039; },\n      { offset: 1, transform: &#039;scale(1)&#039; }\n    ]);\n\n  const cartColorAnimation = this.animationCtrl.create(&#039;cart-color-animation&#039;)\n    .addElement(this.cartFabBnt.nativeElement)\n    .fromTo(&#039;transform&#039;, &#039;rotate(0deg)&#039;, &#039;rotate(45deg)&#039;);\n\n\n  const parent = this.animationCtrl.create(&#039;parent&#039;)\n    .duration(300)\n    .easing(&#039;ease-out&#039;)\n    .iterations(2)\n    .direction(&#039;alternate&#039;)\n    .addAnimation([cartColorAnimation, cartAnimation]);\n\n  \/\/ Playing the parent starts both animations\n  parent.play();\n}\n<\/code><\/pre>\n<p>You can now see both animations playing at the same time on different elements.<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-chain-animations.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-chain-animations.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>There&#8217;s a lot more you can do like removing certain classes with <code>beforeRemoveClass()<\/code> or <code>beforeClearStyles<\/code> and you can also do the opposite after an animation finishes to add a class back again.<\/p>\n<p>Check out the whole <a href=\"https:\/\/ionicframework.com\/docs\/utilities\/animations\">Ionic animations API<\/a> for all possibilities and to create your own epic animations!<\/p>\n<h2>Simple Ionic Gestures<\/h2>\n<p>Now that we&#8217;ve seen some animations, let&#8217;s take a look at gestures.<\/p>\n<p>To get started, add a simple box to your view like this:<\/p>\n<pre><code class=\"language-html\">&lt;ion-content class=&quot;ion-padding-top&quot;&gt;\n  &lt;div #box\n    [ngStyle]=&quot;{&#039;width&#039;: &#039;100px&#039;, &#039;height&#039;: &#039;100px&#039;, &#039;background&#039;: &#039;var(--ion-color-secondary&#039;}&quot;&gt;\n  &lt;\/div&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>The definition of gestures requires certain values again:<\/p>\n<ul>\n<li>The actual DOM element which reacts to the gesture<\/li>\n<li>A threshold after which the gesture starts to prevent issues with scrolling or other functionality<\/li>\n<li>A name for the gesture<\/li>\n<li>Handling the gesture with <code>onStart<\/code> <code>onMove<\/code> and <code>onEnd<\/code><\/li>\n<li>Enable the gesture by calling <code>enable(true)<\/code> on the <code>Gesture<\/code><\/li>\n<\/ul>\n<p>Since you add the gesture to a ViewChild, you need to make sure you are running this inside the <code>ngAfterViewInit<\/code> or later as your ViewChild won&#8217;t be available before that time in the view lifecycle.<\/p>\n<p>In our example, let&#8217;s say we want to simply move the box around inside the view (<em>I know, not the most realistic example<\/em>).<\/p>\n<p>For this, we basically only need to get the <strong>coordinates<\/strong> of our touch gesture while dragging the item, which will be called whenever we move our finger on the screen.<\/p>\n<p>So let&#8217;s move our element around with this gesture:<\/p>\n<pre><code class=\"language-ts\">import { AfterViewInit, Component, ElementRef, ViewChild } from &#039;@angular\/core&#039;;\nimport { DomController, GestureController, IonHeader } from &#039;@ionic\/angular&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage implements AfterViewInit {\n  @ViewChild(&#039;box&#039;, { read: ElementRef }) box: ElementRef;\n  @ViewChild(IonHeader, { read: ElementRef }) header: ElementRef\n  power = 0;\n  longPressActive = false;\n\n  constructor(private gestureCtrl: GestureController, private domCtrl: DomController) { }\n\n  async ngAfterViewInit() {\n    \/\/ Use DomCtrl to get the correct header height\n    await this.domCtrl.read(() =&gt; {\n      const headerHeight = this.header.nativeElement.offsetHeight;\n      this.setupGesture(headerHeight)\n    });\n  }\n\n  setupGesture(headerHeight) {\n    const moveGesture = this.gestureCtrl.create({\n      el: this.box.nativeElement,\n      threshold: 0,\n      gestureName: &#039;move&#039;,\n      onStart: ev =&gt; {\n        console.log(&#039;move start!&#039;);\n      },\n      onMove: ev =&gt; {\n        console.log(ev);\n\n        const currentX = ev.currentX;\n        const currentY = ev.currentY;\n\n        this.box.nativeElement.style.transform = `translate(${currentX}px, ${currentY-headerHeight}px)`;\n      },\n      onEnd: ev =&gt; {\n        console.log(&#039;move end!&#039;);\n      }\n    });\n\n    \/\/ Don&#039;t forget to enable!\n    moveGesture.enable(true);\n  }\n\n}\n<\/code><\/pre>\n<p>There&#8217;s also an additional block before setting up the gesture to get the correct height of the header, since otherwise the gesture would respoisiton the element incorrectly.<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-gesture.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-gesture.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>This was a pretty basic example, let&#8217;s do a bit more!<\/p>\n<h2>Ionic Long Press Gesture<\/h2>\n<p>Over the years the question for a long press gesture came up over and over again, and with gestures you can easily create this on your own now.<\/p>\n<p>First of all, let&#8217;s create a button that we can use for our gesture:<\/p>\n<pre><code class=\"language-html\">&lt;ion-content class=&quot;ion-padding-top&quot;&gt;\n  &lt;ion-button expand=&quot;full&quot; #powerBtn&gt;\n    Increase Power: {{ power }}\n    &lt;ion-icon name=&quot;flame&quot; slot=&quot;end&quot;&gt;&lt;\/ion-icon&gt;\n  &lt;\/ion-button&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>Now we can go ahead and create another gesture almost like before, but this time we especially use <code>onStart<\/code> to set a <code>longPressActive<\/code> to true, and we will revert this inside the <code>onEnd<\/code><\/p>\n<p>Inside the start callback we also trigger our own <code>increasePower()<\/code> function that will continue to run until the long press is not active anymore. While it runs, it will increase the <code>power<\/code> variable a bit faster with every run.<\/p>\n<p>Go ahead and give this second gesture a try by changing your class to:<\/p>\n<pre><code class=\"language-ts\">import { AfterViewInit, Component, ElementRef, ViewChild } from &#039;@angular\/core&#039;;\nimport { GestureController } from &#039;@ionic\/angular&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage implements AfterViewInit {\n  @ViewChild(&#039;powerBtn&#039;, { read: ElementRef }) powerBtn: ElementRef;\n  power = 0;\n  longPressActive = false;\n\n  constructor(private gestureCtrl: GestureController) { }\n\n  ngAfterViewInit() {\n    const longPress = this.gestureCtrl.create({\n      el: this.powerBtn.nativeElement,\n      threshold: 0,\n      gestureName: &#039;long-press&#039;,\n      onStart: ev =&gt; {\n        this.longPressActive = true;\n        this.increasePower();\n      },\n      onEnd: ev =&gt; {\n        this.longPressActive = false;\n      }\n    }, true); \/\/ Passing true will run the gesture callback inside of NgZone!\n\n    \/\/ Don&#039;t forget to enable!\n    longPress.enable(true);\n  }\n\n  increasePower(timeout = 200) {\n    setTimeout(() =&gt; {\n      if (this.longPressActive) {\n          this.power++;\n          this.increasePower(timeout\/1.2);\n      }\n    }, timeout);\n  }\n}\n<\/code><\/pre>\n<p>This time there&#8217;s also a special case, since usually the callback functions of the gestures don&#8217;t run within Angular\u2019s <code>NgZone<\/code> Normally, this means the view wouldn&#8217;t be updated although we changed a variable inside our function.<\/p>\n<p>But you can easily change this by adding <code>true<\/code> at the end of the gesture definition (like we did in the above snippet) to fix this problem.<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-long-press-gesture.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-long-press-gesture.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>Of course this is not the only way to implement a long press &#8211; you can also see an <a href=\"https:\/\/github.com\/ionic-team\/ionic-framework\/pull\/19861\/files#diff-a2605d2bd1fc592f6fb0808816e8ea0f9dc308a7aa7d5b30d948c2cfc494e8fe\">implementation of this concept by Liam from Ionic here<\/a>.<\/p>\n<p>More examples of helpful gesture are <a href=\"https:\/\/ionicacademy.com\/ionic-parallax-image\/\">parallax image scrolling<\/a> or a custom <a href=\"https:\/\/ionicacademy.com\/ionic-bottom-drawer\/\">bottom drawer component<\/a>!<\/p>\n<h2>Combining Gestures and Animations<\/h2>\n<p>Now that we understand the basics of animations and gestures, the next logical step is to combine them to create even better interactive elements inside your Ionic app.<\/p>\n<p>One thing you can quite easily create with a combination is a custom slide to delete functionality for your items.<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-slide-delete-gesture.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-slide-delete-gesture.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>Although we already got the <a href=\"https:\/\/ionicframework.com\/docs\/api\/item-sliding\">ion-item-sliding<\/a>, it never felt 100% correct to me since usually you can completely swipe out an item (like inside a mail application) which removes that row.<\/p>\n<p>Now let&#8217;s create this by first of all setting up a few dummy items inside our view:<\/p>\n<pre><code class=\"language-html\">&lt;ion-content&gt;\n  &lt;div class=&quot;item-container&quot; *ngFor=&quot;let i of myArray&quot; #container&gt;\n    &lt;ion-item&gt;\n      &lt;ion-label&gt;\n        Dummy item {{ i }}\n      &lt;\/ion-label&gt;\n    &lt;\/ion-item&gt;\n    &lt;div class=&quot;icon-row&quot;&gt;\n      &lt;div class=&quot;icon-container&quot;&gt;\n        &lt;ion-icon name=&quot;trash&quot;&gt;&lt;\/ion-icon&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>If you plan to use this gesture, I recommend to put the whole <code>div<\/code> into a shared component instead of implementing it right inside one page.<\/p>\n<p>But for now, we don&#8217;t want to change too many files.<\/p>\n<p>To make it look like the <code>ion-item<\/code> covers the <code>icon-row<\/code> div in the beginning, we can use a bit of CSS and use the grid layout for our elements:<\/p>\n<pre><code class=\"language-css\">.item-container {\n  background-color: var(--ion-color-danger);\n  display: grid;\n}\n\nion-item {\n  grid-column: 1;\n  grid-row: 1;\n}\n\n.icon-row {\n  grid-column: 1;\n  grid-row: 1;\n  display: grid;\n  align-items: center;\n  text-align: right;\n  color: #fff;\n  margin-right: 20px;\n}\n<\/code><\/pre>\n<p>The list looks still the same, but now the container has a red background color (not visible at the moment) and the row with our icon is behind the actual <code>ion-item<\/code> Cool.<\/p>\n<p>So how do you go about tackling a complex gesture and animation like this?<\/p>\n<ul>\n<li>Since we got a list of items, we can access each of them inside a <code>QueryList<\/code> using the <code>@ViewChildren<\/code> decorator this time<\/li>\n<li>We need to add a gesture to each item in that list and allow moving it to the left and right along the <strong>x axis<\/strong>, therefore we set the <code>direction<\/code> only to x<\/li>\n<li>When an item is moved, we will transform the X position like in the example before<\/li>\n<\/ul>\n<p>That&#8217;s basically the gesture part of this example, since this is already enough to move an item to the left and right to reveal the underlying background and delete icon.<\/p>\n<p>We have actually also already defined our <code>deleteAnimation<\/code> above the gesture but not used it yet, since we want to add it inside the <code>onEnd<\/code> callback now!<\/p>\n<p>If the <code>deltaX<\/code> (the change along the x axis) crosses a certain value, we will play our animation which simply changes the height of the container element to zero. If that&#8217;s not the case (the item was moved just a bit perhaps), we will simply slide it back into its original position.<\/p>\n<p>Enough said, here&#8217;s the code for our custom swipe to delete gesture &amp; animation:<\/p>\n<pre><code class=\"language-ts\">import { AfterViewInit, Component, ElementRef, QueryList, ViewChildren } from &#039;@angular\/core&#039;;\nimport { AnimationController, DomController, GestureController, ToastController } from &#039;@ionic\/angular&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage implements AfterViewInit {\n  @ViewChildren(&#039;container&#039;, { read: ElementRef }) itemContainer: QueryList&lt;ElementRef&gt;;\n  myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n  constructor(private gestureCtrl: GestureController, private animationCtrl: AnimationController, private domCtrl: DomController, private toastCtrl: ToastController) { }\n\n  ngAfterViewInit() {\n    const windowWidth = window.innerWidth;\n    const containerArray = this.itemContainer.toArray();\n\n    for (let i = 0; i &lt; containerArray.length; i++) {\n      const containerElement = containerArray[i].nativeElement;\n\n      \/\/ We know the ion-item is the first child of teachhe container element\n      const itemElement = containerElement.childNodes[0];\n\n      const deleteAnimation = this.animationCtrl.create()\n        .addElement(containerElement)\n        .duration(200)\n        .easing(&#039;ease-out&#039;)\n        .fromTo(&#039;height&#039;, &#039;48px&#039;, &#039;0&#039;);\n\n      const swipeGesture = this.gestureCtrl.create({\n        el: itemElement,\n        threshold: 15,\n        direction: &#039;x&#039;,\n        gestureName: &#039;swipe-delete&#039;,\n        onMove: ev =&gt; {\n          const currentX = ev.deltaX;\n\n          this.domCtrl.write(() =&gt; {\n            \/\/ Make sure the item is above the other elements\n            itemElement.style.zIndex = 2;\n            \/\/ Reposition the item\n            itemElement.style.transform = `translateX(${currentX}px)`;\n          });\n        },\n        onEnd: ev =&gt; {\n          itemElement.style.transition = &#039;0.2s ease-out&#039;;\n\n          \/\/ Fly out the element if we cross the threshold of 150px\n          if (ev.deltaX &lt; -150) {\n            this.domCtrl.write(() =&gt; {\n              itemElement.style.transform = `translate3d(-${windowWidth}px, 0, 0)`;\n            });\n            deleteAnimation.play();\n\n            deleteAnimation.onFinish(async () =&gt; {\n              this.myArray = this.myArray.filter(number =&gt; number != i + 1);\n\n              const toast = await this.toastCtrl.create({\n                message: `Item ${i + 1} removed.`,\n                duration: 2000\n              });\n              toast.present();\n            });\n          } else {\n            \/\/ Fly the item back into the original position\n            this.domCtrl.write(() =&gt; {\n              itemElement.style.transform = &#039;&#039;;\n            });\n          }\n        }\n      }, true);\n\n      \/\/ Don&#039;t forget to enable!\n      swipeGesture.enable(true);\n    }\n  }\n\n}\n<\/code><\/pre>\n<p>The animation alone only changes the height, but we also need to fly out the element, so we use the <code>DomController<\/code> again to shift the item out of the view &#8211; if you read carefully you could also chain the animations together without even using this additional block and create one animation that first decreases the height and then moves the item.<\/p>\n<p>Finally, this is all just DOM operation, so we add another function to the <code>onFinish<\/code> callback of the gesture (<em>yes, that exists!<\/em>) so we can safely remove the item from our local array, which completes the whole slide to remove gesture!<\/p>\n<p>It&#8217;s actually kinda fun to create these kinds of gesture and animation combinations, and if you want another example check out my popular <a href=\"https:\/\/ionicacademy.com\/custom-gestures-ionic\/\">Tinder swipe gesture tutorial<\/a>!<\/p>\n<h2>Using Animations for Modals<\/h2>\n<p>After seeing the different use cases for animations and gestures in our Ionic app, let&#8217;s wrap this up by taking a look at another option: Defining your custom animations for page or modal transitions!<\/p>\n<p>You heard right, you can define your own transitions and use them instead of the e.g. standard modal appear animation.<\/p>\n<p>As a starting point, I highly recommend you check out the current implementation which you can easily find <a href=\"https:\/\/github.com\/ionic-team\/ionic-framework\/tree\/master\/core\/src\/components\/modal\/animations\">within the Ionic Github repository<\/a>.<\/p>\n<p>If you use this file as the base, you can change all parts quite easily to your need and build a (<em>more or less<\/em>) helpful other transitions like the one below.<\/p>\n<p>To use it, simply create a new file inside your app at <strong>src\/app\/modal-animation.ts<\/strong> and insert:<\/p>\n<pre><code class=\"language-ts\">import { Animation, createAnimation } from &#039;@ionic\/angular&#039;;\n\nexport const modalEnterAnimation = (\n    baseEl: HTMLElement,\n    presentingEl?: HTMLElement,\n  ): Animation =&gt; {\n\n\n  const backdropAnimation = createAnimation()\n    .addElement(baseEl.querySelector(&#039;ion-backdrop&#039;)!)\n    .fromTo(&#039;opacity&#039;, 0.01, &#039;var(--backdrop-opacity)&#039;)\n    .beforeStyles({\n      &#039;pointer-events&#039;: &#039;none&#039;\n    })\n    .afterClearStyles([&#039;pointer-events&#039;]);\n\n  const wrapperAnimation = createAnimation()\n    .addElement(baseEl.querySelectorAll(&#039;.modal-wrapper, .modal-shadow&#039;)!)\n    .beforeStyles({ &#039;opacity&#039;: 1 })\n    .keyframes([\n        { offset: 0, transform: &#039;translateY(-100vh)&#039; },\n        { offset: 0.4, transform: &#039;translateY(20vh)&#039;},\n        { offset: 0.7, transform: &#039;translateY(-10vh)&#039;},\n        { offset: 1, transform: &#039;translateY(0vh)&#039;},\n      ]);\n\n  const baseAnimation = createAnimation()\n    .addElement(baseEl)\n    .easing(&#039;ease-out&#039;)\n    .duration(900)\n    .addAnimation([wrapperAnimation, backdropAnimation]);\n\n  return baseAnimation;\n};\n\n<\/code><\/pre>\n<p>This animation will show the backdrop like the regular modal appear, but then somehow <em>bounce<\/em> in the next page. I&#8217;m sure you will come up with better animations than I did for your own app.<\/p>\n<p>There are two ways to use your custom animations:<\/p>\n<ul>\n<li>Define them while opening a modal<\/li>\n<li>Define them as the standard inside the Ionic config at the App module<\/li>\n<\/ul>\n<p>For the modal let&#8217;s simply use it directly when presenting a modal. This is really just passing in your exported <code>modalEnterAnimation<\/code> to the <code>enterAnimation<\/code> of the modal like this:<\/p>\n<pre><code class=\"language-ts\">import { Component } from &#039;@angular\/core&#039;;\nimport { ModalController } from &#039;@ionic\/angular&#039;;\nimport { modalEnterAnimation } from &#039;..\/modal-animation&#039;;\nimport { MyModalPage } from &#039;..\/my-modal\/my-modal.page&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n\n  constructor(private modalCtrl: ModalController) { }\n\n  async presentModal() {\n    const modal = await this.modalCtrl.create({\n      component: MyModalPage,\n      showBackdrop: true,\n      backdropDismiss: true,\n      enterAnimation: modalEnterAnimation,\n      cssClass: &#039;custom-modal&#039;\n    });\n\n    await modal.present();\n  }\n}\n<\/code><\/pre>\n<p>To make the modal stand out a bit more and see the animation more clearly I also used a custom class for the modal which you need to define inside the <strong>src\/global.scss<\/strong>:<\/p>\n<pre><code class=\"language-css\">.custom-modal {\n    .modal-wrapper {\n        width: 80%;\n        height: 80%;\n    }\n}\n<\/code><\/pre>\n<p>This just changes the size of the modal a bit so it looks cooler above our current page!<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-modal-enter.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-modal-enter.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>You can basically define your own transition for any kind of overlay component that Ionic offers.<\/p>\n<h2>Changing the Ionic Page Transition Animation<\/h2>\n<p>As said before, you can also change the way your page transition looks like when using the Angular router.<\/p>\n<p>And just like with the modal animation, you can either define them directly when navigating on a per-component basis or within your glocal Ionic config.<\/p>\n<p>Defining a transition for pages is a bit more difficult, as you can see from the standard <a href=\"https:\/\/github.com\/ionic-team\/ionic-framework\/tree\/master\/core\/src\/utils\/transition\">Ionic definition for page transitions on Github<\/a>.<\/p>\n<p>In this case, you can animate both the entering element and the leaving element to compose your own unique transition.<\/p>\n<p>Let&#8217;s say we want to simply fade our pages instead of the regular transition. In that case, we can create a new file at <strong>src\/app\/nav-animation.ts<\/strong> and check for the <code>direction<\/code> property of the options to create the right animation order for our elements:<\/p>\n<pre><code class=\"language-ts\">import { Animation, createAnimation } from &#039;@ionic\/angular&#039;;\n\nexport const enterAnimation = (baseEl: HTMLElement, opts?: any): Animation =&gt; {\n    const DURATION = 1000;\n\n    if (opts.direction === &#039;forward&#039;) {\n        \/\/ Fade in the next page\n        return createAnimation()\n        .addElement(opts.enteringEl)\n        .duration(DURATION)\n        .easing(&#039;ease-in&#039;)\n        .fromTo(&#039;opacity&#039;, 0, 1);\n    } else if (opts.direction === &#039;back&#039;) {\n        \/\/ Fade in the previous page\n        const rootAnimation = createAnimation()\n        .addElement(opts.enteringEl)\n        .duration(DURATION)\n        .easing(&#039;ease-out&#039;)\n        .fromTo(&#039;opacity&#039;, 0, 1);\n\n        \/\/ Fade out the current top page\n        const leavingAnim = createAnimation()\n        .addElement(opts.leavingEl)\n        .duration(DURATION)\n        .easing(&#039;ease-out&#039;)\n        .fromTo(&#039;opacity&#039;, 1, 0);\n\n        \/\/ Chain both animations\n        return createAnimation().addAnimation([rootAnimation, leavingAnim]);\n    }\n};\n\n<\/code><\/pre>\n<p>But as you can see after a few examples &#8211; the basic syntax and creation of animations is always the same, so pick up the API and functions once and you are free to create any kind of powerful animation!<\/p>\n<p>To use our custom animation, you can pass it right to the <a href=\"https:\/\/ionicframework.com\/docs\/angular\/config#config-options\">config object of your Ionic app<\/a> like this:<\/p>\n<pre><code class=\"language-ts\">import { enterAnimation } from &#039;.\/nav-animation&#039;;\n\n@NgModule({\n  declarations: [AppComponent],\n  entryComponents: [],\n  imports: [BrowserModule, IonicModule.forRoot({\n    navAnimation: enterAnimation \/\/ Add your animations!\n  }), AppRoutingModule],\n  providers: [\n    StatusBar,\n    SplashScreen,\n    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }\n  ],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n<\/code><\/pre>\n<p>Now all page transitions inside your app would use this new animation, you can simply use any kind of standard routing through the Angular router like:<\/p>\n<pre><code class=\"language-ts\">constructor(private router: Router) { }\n\nnavigateToPage() {\n  this.router.navigateByUrl(&#039;my-modal&#039;);\n}\n<\/code><\/pre>\n<p>If that&#8217;s too much for you and you just need a decent animation in <em>some<\/em> places of your app, you can also use the Ionic <code>NavController<\/code> to define the animation for <strong>the next transition<\/strong>!<\/p>\n<p>That means, calling <code>setDirection()<\/code> won&#8217;t directly change your page, but when the next transition happens, your defined transition and custom animation will be consumed:<\/p>\n<pre><code class=\"language-ts\">import { Component } from &#039;@angular\/core&#039;;\nimport { Router } from &#039;@angular\/router&#039;;\nimport { NavController } from &#039;@ionic\/angular&#039;;\nimport { enterAnimation } from &#039;..\/nav-animation&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n\n  constructor(private router: Router, private navCtrl: NavController) { }\n\n  navigateToPage() {\n    \/\/ Define the animation for the transition!\n    this.navCtrl.setDirection(&#039;forward&#039;, true, &#039;forward&#039;, enterAnimation);\n    this.router.navigateByUrl(&#039;my-modal&#039;);\n  }\n}\n<\/code><\/pre>\n<p>Now we have completely changed the transition between two pages:<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-custom-nav-transition.gif\" alt=\"\" class=\"aligncenter lazyload\" style=\"--smush-placeholder-width: 1096px; --smush-placeholder-aspect-ratio: 1096\/2128;width:300px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/ionic-custom-nav-transition.gif\" alt=\"\" class=\"aligncenter\" style=\"width:300px\" \/><\/noscript><\/p>\n<p>It&#8217;s actually quite amazing to see how easy these core parts of your Ionic app can be changed, given that we only defined one additional file and used it in the right places.<\/p>\n<h2>Conclusion<\/h2>\n<p>Improving your Ionic app with small animations and additional gestures can have a big impact on the overall user experience, and using the built in Ionic APIs makes working with them a breeze.<\/p>\n<p>These were just a handful of examples, but you can basically do anything: Add a double tap gesture, create powerful directives or use advanced custom page transitions!<\/p>\n<p>If you want to learn even more about Ionic with a library of 60+ video courses, templates and a supportive community, you can <a href=\"https:\/\/ionicacademy.com\/\">join the Ionic Academy<\/a> and get access to a ton of learning material to boost your Ionic development skills.<\/p>\n<p>And don\u2019t forget to <a href=\"https:\/\/www.youtube.com\/user\/saimon1924\">subscribe to my YouTube channel<\/a> for fresh Ionic tutorials coming every week!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. Since Ionic 5 we got access to a great Animations and Gestures utility API, which can help to add [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":3561,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"1","publish_post_category":"23","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"491683","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/building-interactive-ionic-apps-with-gestures-and-animations\/201375","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[121,124],"tags":[60,166,199,25],"class_list":["post-3553","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","category-tutorials","tag-angular","tag-animations","tag-gestures","tag-tutorials"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building Interactive Ionic Apps with Gestures and Animations - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building Interactive Ionic Apps with Gestures and Animations\" \/>\n<meta property=\"og:description\" content=\"This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. Since Ionic 5 we got access to a great Animations and Gestures utility API, which can help to add [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-16T16:18:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1489\" \/>\n\t<meta property=\"og:image:height\" content=\"838\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Simon Grimm\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@schlimmson\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Simon Grimm\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"18 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\"},\"author\":{\"name\":\"Simon Grimm\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\"},\"headline\":\"Building Interactive Ionic Apps with Gestures and Animations\",\"datePublished\":\"2020-12-16T16:18:12+00:00\",\"dateModified\":\"2020-12-16T16:18:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\"},\"wordCount\":2297,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp\",\"keywords\":[\"Angular\",\"Animations\",\"Gestures\",\"Tutorials\"],\"articleSection\":[\"Engineering\",\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\",\"url\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\",\"name\":\"Building Interactive Ionic Apps with Gestures and Animations - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp\",\"datePublished\":\"2020-12-16T16:18:12+00:00\",\"dateModified\":\"2020-12-16T16:18:12+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp\",\"width\":1489,\"height\":838},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Building Interactive Ionic Apps with Gestures and Animations\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\",\"name\":\"Simon Grimm\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"caption\":\"Simon Grimm\"},\"sameAs\":[\"https:\/\/x.com\/schlimmson\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/schlimmson\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Building Interactive Ionic Apps with Gestures and Animations - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations","og_locale":"en_US","og_type":"article","og_title":"Building Interactive Ionic Apps with Gestures and Animations","og_description":"This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. Since Ionic 5 we got access to a great Animations and Gestures utility API, which can help to add [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations","og_site_name":"Ionic Blog","article_published_time":"2020-12-16T16:18:12+00:00","og_image":[{"width":1489,"height":838,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","type":"image\/webp"}],"author":"Simon Grimm","twitter_card":"summary_large_image","twitter_creator":"@schlimmson","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Simon Grimm","Est. reading time":"18 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations"},"author":{"name":"Simon Grimm","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6"},"headline":"Building Interactive Ionic Apps with Gestures and Animations","datePublished":"2020-12-16T16:18:12+00:00","dateModified":"2020-12-16T16:18:12+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations"},"wordCount":2297,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","keywords":["Angular","Animations","Gestures","Tutorials"],"articleSection":["Engineering","Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations","url":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations","name":"Building Interactive Ionic Apps with Gestures and Animations - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","datePublished":"2020-12-16T16:18:12+00:00","dateModified":"2020-12-16T16:18:12+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","width":1489,"height":838},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/building-interactive-ionic-apps-with-gestures-and-animations#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Building Interactive Ionic Apps with Gestures and Animations"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6","name":"Simon Grimm","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","caption":"Simon Grimm"},"sameAs":["https:\/\/x.com\/schlimmson"],"url":"https:\/\/ionic.io\/blog\/author\/schlimmson"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/12\/photo-1518932945647-7a1c969f8be2.webp","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=3553"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3553\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/3561"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=3553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=3553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=3553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}