{"id":2575,"date":"2020-12-30T12:58:49","date_gmt":"2020-12-30T12:58:49","guid":{"rendered":"https:\/\/ntspl.co.in\/blog\/?p=2575"},"modified":"2023-01-31T08:04:42","modified_gmt":"2023-01-31T08:04:42","slug":"building-interactive-ionic-apps-with-gestures-and-animations","status":"publish","type":"post","link":"https:\/\/www.ntspl.co.in\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\/","title":{"rendered":"Building Interactive Ionic Apps with Gestures and Animations"},"content":{"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<\/p>\n<p>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\u00a0<strong>slide to delete<\/strong>\u00a0feature and finally use our own animations for Ionic page transitions!<\/p>\n<h2>Prerequisite<\/h2>\n<p>The coolest thing about all this upfront: You don\u2019t 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 hljs\">ionic start ionicInteractive blank --<span class=\"hljs-built_in\">type<\/span>=angular --capacitor\r\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 \u201cbehind the scenes\u201d on why those APIs were created in the first place, travel back in time to the\u00a0<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\u2019s 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\u00a0<code>ViewChild<\/code>\u00a0later.<\/p>\n<p>Open the\u00a0<strong>home\/home.page.html<\/strong>\u00a0and change it to:<\/p>\n<pre><code class=\"language-html hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-header<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-toolbar<\/span> <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"primary\"<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-title<\/span>&gt;<\/span>\r\n      Ionic Interactive\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-title<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-toolbar<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-header<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-content<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ion-padding-top\"<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-button<\/span> <span class=\"hljs-attr\">expand<\/span>=<span class=\"hljs-string\">\"full\"<\/span> (<span class=\"hljs-attr\">click<\/span>)=<span class=\"hljs-string\">\"startLoad()\"<\/span>&gt;<\/span>\r\n    Load\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-icon<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"reload\"<\/span> <span class=\"hljs-attr\">slot<\/span>=<span class=\"hljs-string\">\"end\"<\/span> #<span class=\"hljs-attr\">loadingIcon<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-icon<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-button<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-button<\/span> <span class=\"hljs-attr\">expand<\/span>=<span class=\"hljs-string\">\"full\"<\/span> (<span class=\"hljs-attr\">click<\/span>)=<span class=\"hljs-string\">\"addToCart()\"<\/span> #<span class=\"hljs-attr\">cartBtn<\/span>&gt;<\/span>\r\n    Add to cart\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-button<\/span>&gt;<\/span>\r\n\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-fab<\/span> <span class=\"hljs-attr\">vertical<\/span>=<span class=\"hljs-string\">\"top\"<\/span> <span class=\"hljs-attr\">horizontal<\/span>=<span class=\"hljs-string\">\"end\"<\/span> <span class=\"hljs-attr\">slot<\/span>=<span class=\"hljs-string\">\"fixed\"<\/span> <span class=\"hljs-attr\">edge<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-fab-button<\/span> #<span class=\"hljs-attr\">cartFabBtn<\/span> <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"secondary\"<\/span>&gt;<\/span>\r\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-icon<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"cart\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-icon<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-fab-button<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-fab<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-content<\/span>&gt;<\/span>\r\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\u2019t 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\u00a0<code>Animation<\/code>\u00a0with the\u00a0<code>AnimationController<\/code>\u00a0and 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\u00a0<code>play()<\/code>\u00a0on the created\u00a0<code>Animation<\/code><\/li>\n<\/ul>\n<p>That\u2019s the core idea, and you can then define various elements of the animation like the\u00a0<strong>duration<\/strong>\u00a0(<em>how long should the animation play?<\/em>),\u00a0<strong>iterations<\/strong>\u00a0(<em>how often should the animation run?<\/em>) and the actual animation with keyframes or the simple\u00a0<code>fromTo()<\/code>\u00a0operator.<\/p>\n<p>For now, let\u2019s simply rotate the icon 3 times, where each iteration takes 1.5 seconds.<\/p>\n<p>Therefore, open the\u00a0<strong>home\/home.page.ts<\/strong>\u00a0and change it to:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { Component, ElementRef, ViewChild } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { AnimationController } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage {\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(<span class=\"hljs-string\">'loadingIcon'<\/span>, { read: ElementRef }) loadingIcon: ElementRef;\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(<span class=\"hljs-string\">'cartBtn'<\/span>, { read: ElementRef }) cartBnt: ElementRef;\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(<span class=\"hljs-string\">'cartFabBtn'<\/span>, { read: ElementRef }) cartFabBnt: ElementRef;\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> animationCtrl: AnimationController<\/span>) { }\r\n\r\n  startLoad() {\r\n    <span class=\"hljs-keyword\">const<\/span> loadingAnimation = <span class=\"hljs-built_in\">this<\/span>.animationCtrl.create(<span class=\"hljs-string\">'loading-animation'<\/span>)\r\n      .addElement(<span class=\"hljs-built_in\">this<\/span>.loadingIcon.nativeElement)\r\n      .duration(<span class=\"hljs-number\">1500<\/span>)\r\n      .iterations(<span class=\"hljs-number\">3<\/span>)\r\n      .fromTo(<span class=\"hljs-string\">'transform'<\/span>, <span class=\"hljs-string\">'rotate(0deg)'<\/span>, <span class=\"hljs-string\">'rotate(360deg)'<\/span>);\r\n\r\n    <span class=\"hljs-comment\">\/\/ Don't forget to start the animation!<\/span>\r\n    loadingAnimation.play();\r\n  }\r\n}\r\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\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-animation.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/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\u00a0<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 hljs typescript\">addToCart() {\r\n  <span class=\"hljs-keyword\">const<\/span> cartAnimation = <span class=\"hljs-built_in\">this<\/span>.animationCtrl.create(<span class=\"hljs-string\">'cart-animation'<\/span>)\r\n    .addElement(<span class=\"hljs-built_in\">this<\/span>.cartBnt.nativeElement)\r\n    .keyframes([\r\n      { offset: <span class=\"hljs-number\">0<\/span>, transform: <span class=\"hljs-string\">'scale(1)'<\/span> },\r\n      { offset: <span class=\"hljs-number\">0.5<\/span>, transform: <span class=\"hljs-string\">'scale(1.2)'<\/span> },\r\n      { offset: <span class=\"hljs-number\">0.8<\/span>, transform: <span class=\"hljs-string\">'scale(0.9)'<\/span> },\r\n      { offset: <span class=\"hljs-number\">1<\/span>, transform: <span class=\"hljs-string\">'scale(1)'<\/span> }\r\n    ]);\r\n\r\n  <span class=\"hljs-keyword\">const<\/span> cartColorAnimation = <span class=\"hljs-built_in\">this<\/span>.animationCtrl.create(<span class=\"hljs-string\">'cart-color-animation'<\/span>)\r\n    .addElement(<span class=\"hljs-built_in\">this<\/span>.cartFabBnt.nativeElement)\r\n    .fromTo(<span class=\"hljs-string\">'transform'<\/span>, <span class=\"hljs-string\">'rotate(0deg)'<\/span>, <span class=\"hljs-string\">'rotate(45deg)'<\/span>);\r\n\r\n\r\n  <span class=\"hljs-keyword\">const<\/span> parent = <span class=\"hljs-built_in\">this<\/span>.animationCtrl.create(<span class=\"hljs-string\">'parent'<\/span>)\r\n    .duration(<span class=\"hljs-number\">300<\/span>)\r\n    .easing(<span class=\"hljs-string\">'ease-out'<\/span>)\r\n    .iterations(<span class=\"hljs-number\">2<\/span>)\r\n    .direction(<span class=\"hljs-string\">'alternate'<\/span>)\r\n    .addAnimation([cartColorAnimation, cartAnimation]);\r\n\r\n  <span class=\"hljs-comment\">\/\/ Playing the parent starts both animations<\/span>\r\n  parent.play();\r\n}\r\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\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-chain-animations.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/p>\n<p>There\u2019s a lot more you can do like removing certain classes with\u00a0<code>beforeRemoveClass()<\/code>\u00a0or\u00a0<code>beforeClearStyles<\/code>\u00a0and you can also do the opposite after an animation finishes to add a class back again.<\/p>\n<p>Check out the whole\u00a0<a href=\"https:\/\/ionicframework.com\/docs\/utilities\/animations\">Ionic animations API<\/a>\u00a0for all possibilities and to create your own epic animations!<\/p>\n<h2>Simple Ionic Gestures<\/h2>\n<p>Now that we\u2019ve seen some animations, let\u2019s 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 hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-content<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ion-padding-top\"<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> #<span class=\"hljs-attr\">box<\/span>\r\n    [<span class=\"hljs-attr\">ngStyle<\/span>]=<span class=\"hljs-string\">\"{'width': '100px', 'height': '100px', 'background': 'var(--ion-color-secondary'}\"<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-content<\/span>&gt;<\/span>\r\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\u00a0<code>onStart<\/code>\u00a0<code>onMove<\/code>\u00a0and\u00a0<code>onEnd<\/code><\/li>\n<li>Enable the gesture by calling\u00a0<code>enable(true)<\/code>\u00a0on the\u00a0<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\u00a0<code>ngAfterViewInit<\/code>\u00a0or later as your ViewChild won\u2019t be available before that time in the view lifecycle.<\/p>\n<p>In our example, let\u2019s 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\u00a0<strong>coordinates<\/strong>\u00a0of our touch gesture while dragging the item, which will be called whenever we move our finger on the screen.<\/p>\n<p>So let\u2019s move our element around with this gesture:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { AfterViewInit, Component, ElementRef, ViewChild } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { DomController, GestureController, IonHeader } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage <span class=\"hljs-keyword\">implements<\/span> AfterViewInit {\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(<span class=\"hljs-string\">'box'<\/span>, { read: ElementRef }) box: ElementRef;\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(IonHeader, { read: ElementRef }) header: ElementRef\r\n  power = <span class=\"hljs-number\">0<\/span>;\r\n  longPressActive = <span class=\"hljs-literal\">false<\/span>;\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> gestureCtrl: GestureController, <span class=\"hljs-keyword\">private<\/span> domCtrl: DomController<\/span>) { }\r\n\r\n  <span class=\"hljs-keyword\">async<\/span> ngAfterViewInit() {\r\n    <span class=\"hljs-comment\">\/\/ Use DomCtrl to get the correct header height<\/span>\r\n    <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-built_in\">this<\/span>.domCtrl.read(<span class=\"hljs-function\">() =&gt;<\/span> {\r\n      <span class=\"hljs-keyword\">const<\/span> headerHeight = <span class=\"hljs-built_in\">this<\/span>.header.nativeElement.offsetHeight;\r\n      <span class=\"hljs-built_in\">this<\/span>.setupGesture(headerHeight)\r\n    });\r\n  }\r\n\r\n  setupGesture(headerHeight) {\r\n    <span class=\"hljs-keyword\">const<\/span> moveGesture = <span class=\"hljs-built_in\">this<\/span>.gestureCtrl.create({\r\n      el: <span class=\"hljs-built_in\">this<\/span>.box.nativeElement,\r\n      threshold: <span class=\"hljs-number\">0<\/span>,\r\n      gestureName: <span class=\"hljs-string\">'move'<\/span>,\r\n      onStart: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n        <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'move start!'<\/span>);\r\n      },\r\n      onMove: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n        <span class=\"hljs-built_in\">console<\/span>.log(ev);\r\n\r\n        <span class=\"hljs-keyword\">const<\/span> currentX = ev.currentX;\r\n        <span class=\"hljs-keyword\">const<\/span> currentY = ev.currentY;\r\n\r\n        <span class=\"hljs-built_in\">this<\/span>.box.nativeElement.style.transform = <span class=\"hljs-string\">`translate(<span class=\"hljs-subst\">${currentX}<\/span>px, <span class=\"hljs-subst\">${currentY-headerHeight}<\/span>px)`<\/span>;\r\n      },\r\n      onEnd: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n        <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'move end!'<\/span>);\r\n      }\r\n    });\r\n\r\n    <span class=\"hljs-comment\">\/\/ Don't forget to enable!<\/span>\r\n    moveGesture.enable(<span class=\"hljs-literal\">true<\/span>);\r\n  }\r\n\r\n}\r\n<\/code><\/pre>\n<p>There\u2019s 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\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-simple-gesture.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/p>\n<p>This was a pretty basic example, let\u2019s 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\u2019s create a button that we can use for our gesture:<\/p>\n<pre><code class=\"language-html hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-content<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ion-padding-top\"<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-button<\/span> <span class=\"hljs-attr\">expand<\/span>=<span class=\"hljs-string\">\"full\"<\/span> #<span class=\"hljs-attr\">powerBtn<\/span>&gt;<\/span>\r\n    Increase Power: {{ power }}\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-icon<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"flame\"<\/span> <span class=\"hljs-attr\">slot<\/span>=<span class=\"hljs-string\">\"end\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-icon<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-button<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-content<\/span>&gt;<\/span>\r\n<\/code><\/pre>\n<p>Now we can go ahead and create another gesture almost like before, but this time we especially use\u00a0<code>onStart<\/code>\u00a0to set a\u00a0<code>longPressActive<\/code>\u00a0to true, and we will revert this inside the\u00a0<code>onEnd<\/code><\/p>\n<p>Inside the start callback we also trigger our own\u00a0<code>increasePower()<\/code>\u00a0function that will continue to run until the long press is not active anymore. While it runs, it will increase the\u00a0<code>power<\/code>\u00a0variable 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 hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { AfterViewInit, Component, ElementRef, ViewChild } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { GestureController } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage <span class=\"hljs-keyword\">implements<\/span> AfterViewInit {\r\n  <span class=\"hljs-meta\">@ViewChild<\/span>(<span class=\"hljs-string\">'powerBtn'<\/span>, { read: ElementRef }) powerBtn: ElementRef;\r\n  power = <span class=\"hljs-number\">0<\/span>;\r\n  longPressActive = <span class=\"hljs-literal\">false<\/span>;\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> gestureCtrl: GestureController<\/span>) { }\r\n\r\n  ngAfterViewInit() {\r\n    <span class=\"hljs-keyword\">const<\/span> longPress = <span class=\"hljs-built_in\">this<\/span>.gestureCtrl.create({\r\n      el: <span class=\"hljs-built_in\">this<\/span>.powerBtn.nativeElement,\r\n      threshold: <span class=\"hljs-number\">0<\/span>,\r\n      gestureName: <span class=\"hljs-string\">'long-press'<\/span>,\r\n      onStart: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n        <span class=\"hljs-built_in\">this<\/span>.longPressActive = <span class=\"hljs-literal\">true<\/span>;\r\n        <span class=\"hljs-built_in\">this<\/span>.increasePower();\r\n      },\r\n      onEnd: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n        <span class=\"hljs-built_in\">this<\/span>.longPressActive = <span class=\"hljs-literal\">false<\/span>;\r\n      }\r\n    }, <span class=\"hljs-literal\">true<\/span>); <span class=\"hljs-comment\">\/\/ Passing true will run the gesture callback inside of NgZone!<\/span>\r\n\r\n    <span class=\"hljs-comment\">\/\/ Don't forget to enable!<\/span>\r\n    longPress.enable(<span class=\"hljs-literal\">true<\/span>);\r\n  }\r\n\r\n  increasePower(timeout = <span class=\"hljs-number\">200<\/span>) {\r\n    <span class=\"hljs-built_in\">setTimeout<\/span>(<span class=\"hljs-function\">() =&gt;<\/span> {\r\n      <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-built_in\">this<\/span>.longPressActive) {\r\n          <span class=\"hljs-built_in\">this<\/span>.power++;\r\n          <span class=\"hljs-built_in\">this<\/span>.increasePower(timeout\/<span class=\"hljs-number\">1.2<\/span>);\r\n      }\r\n    }, timeout);\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>This time there\u2019s also a special case, since usually the callback functions of the gestures don\u2019t run within Angular\u2019s\u00a0<code>NgZone<\/code>\u00a0Normally, this means the view wouldn\u2019t be updated although we changed a variable inside our function.<\/p>\n<p>But you can easily change this by adding\u00a0<code>true<\/code>\u00a0at the end of the gesture definition (like we did in the above snippet) to fix this problem.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-long-press-gesture.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/p>\n<p>Of course this is not the only way to implement a long press \u2013 you can also see an\u00a0<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\u00a0<a href=\"https:\/\/ionicacademy.com\/ionic-parallax-image\/\">parallax image scrolling<\/a>\u00a0or a custom\u00a0<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\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-slide-delete-gesture.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/p>\n<p>Although we already got the\u00a0<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\u2019s create this by first of all setting up a few dummy items inside our view:<\/p>\n<pre><code class=\"language-html hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-content<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"item-container\"<\/span> *<span class=\"hljs-attr\">ngFor<\/span>=<span class=\"hljs-string\">\"let i of myArray\"<\/span> #<span class=\"hljs-attr\">container<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-item<\/span>&gt;<\/span>\r\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-label<\/span>&gt;<\/span>\r\n        Dummy item {{ i }}\r\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-label<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-item<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"icon-row\"<\/span>&gt;<\/span>\r\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"icon-container\"<\/span>&gt;<\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ion-icon<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"trash\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-icon<\/span>&gt;<\/span>\r\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ion-content<\/span>&gt;<\/span>\r\n<\/code><\/pre>\n<p>If you plan to use this gesture, I recommend to put the whole\u00a0<code>div<\/code>\u00a0into a shared component instead of implementing it right inside one page.<\/p>\n<p>But for now, we don\u2019t want to change too many files.<\/p>\n<p>To make it look like the\u00a0<code>ion-item<\/code>\u00a0covers the\u00a0<code>icon-row<\/code>\u00a0div 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 hljs\"><span class=\"hljs-selector-class\">.item-container<\/span> {\r\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">var<\/span>(--ion-color-danger);\r\n  <span class=\"hljs-attribute\">display<\/span>: grid;\r\n}\r\n\r\n<span class=\"hljs-selector-tag\">ion-item<\/span> {\r\n  <span class=\"hljs-attribute\">grid-column<\/span>: <span class=\"hljs-number\">1<\/span>;\r\n  <span class=\"hljs-attribute\">grid-row<\/span>: <span class=\"hljs-number\">1<\/span>;\r\n}\r\n\r\n<span class=\"hljs-selector-class\">.icon-row<\/span> {\r\n  <span class=\"hljs-attribute\">grid-column<\/span>: <span class=\"hljs-number\">1<\/span>;\r\n  <span class=\"hljs-attribute\">grid-row<\/span>: <span class=\"hljs-number\">1<\/span>;\r\n  <span class=\"hljs-attribute\">display<\/span>: grid;\r\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\r\n  <span class=\"hljs-attribute\">text-align<\/span>: right;\r\n  <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#fff<\/span>;\r\n  <span class=\"hljs-attribute\">margin-right<\/span>: <span class=\"hljs-number\">20px<\/span>;\r\n}\r\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\u00a0<code>ion-item<\/code>\u00a0Cool.<\/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\u00a0<code>QueryList<\/code>\u00a0using the\u00a0<code>@ViewChildren<\/code>\u00a0decorator 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\u00a0<strong>x axis<\/strong>, therefore we set the\u00a0<code>direction<\/code>\u00a0only 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\u2019s 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\u00a0<code>deleteAnimation<\/code>\u00a0above the gesture but not used it yet, since we want to add it inside the\u00a0<code>onEnd<\/code>\u00a0callback now!<\/p>\n<p>If the\u00a0<code>deltaX<\/code>\u00a0(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\u2019s 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\u2019s the code for our custom swipe to delete gesture &amp; animation:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { AfterViewInit, Component, ElementRef, QueryList, ViewChildren } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { AnimationController, DomController, GestureController, ToastController } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage <span class=\"hljs-keyword\">implements<\/span> AfterViewInit {\r\n  <span class=\"hljs-meta\">@ViewChildren<\/span>(<span class=\"hljs-string\">'container'<\/span>, { read: ElementRef }) itemContainer: QueryList&lt;ElementRef&gt;;\r\n  myArray = [<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-number\">7<\/span>, <span class=\"hljs-number\">8<\/span>, <span class=\"hljs-number\">9<\/span>];\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> gestureCtrl: GestureController, <span class=\"hljs-keyword\">private<\/span> animationCtrl: AnimationController, <span class=\"hljs-keyword\">private<\/span> domCtrl: DomController, <span class=\"hljs-keyword\">private<\/span> toastCtrl: ToastController<\/span>) { }\r\n\r\n  ngAfterViewInit() {\r\n    <span class=\"hljs-keyword\">const<\/span> windowWidth = <span class=\"hljs-built_in\">window<\/span>.innerWidth;\r\n    <span class=\"hljs-keyword\">const<\/span> containerArray = <span class=\"hljs-built_in\">this<\/span>.itemContainer.toArray();\r\n\r\n    <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">let<\/span> i = <span class=\"hljs-number\">0<\/span>; i &lt; containerArray.length; i++) {\r\n      <span class=\"hljs-keyword\">const<\/span> containerElement = containerArray[i].nativeElement;\r\n\r\n      <span class=\"hljs-comment\">\/\/ We know the ion-item is the first child of teachhe container element<\/span>\r\n      <span class=\"hljs-keyword\">const<\/span> itemElement = containerElement.childNodes[<span class=\"hljs-number\">0<\/span>];\r\n\r\n      <span class=\"hljs-keyword\">const<\/span> deleteAnimation = <span class=\"hljs-built_in\">this<\/span>.animationCtrl.create()\r\n        .addElement(containerElement)\r\n        .duration(<span class=\"hljs-number\">200<\/span>)\r\n        .easing(<span class=\"hljs-string\">'ease-out'<\/span>)\r\n        .fromTo(<span class=\"hljs-string\">'height'<\/span>, <span class=\"hljs-string\">'48px'<\/span>, <span class=\"hljs-string\">'0'<\/span>);\r\n\r\n      <span class=\"hljs-keyword\">const<\/span> swipeGesture = <span class=\"hljs-built_in\">this<\/span>.gestureCtrl.create({\r\n        el: itemElement,\r\n        threshold: <span class=\"hljs-number\">15<\/span>,\r\n        direction: <span class=\"hljs-string\">'x'<\/span>,\r\n        gestureName: <span class=\"hljs-string\">'swipe-delete'<\/span>,\r\n        onMove: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n          <span class=\"hljs-keyword\">const<\/span> currentX = ev.deltaX;\r\n\r\n          <span class=\"hljs-built_in\">this<\/span>.domCtrl.write(<span class=\"hljs-function\">() =&gt;<\/span> {\r\n            <span class=\"hljs-comment\">\/\/ Make sure the item is above the other elements<\/span>\r\n            itemElement.style.zIndex = <span class=\"hljs-number\">2<\/span>;\r\n            <span class=\"hljs-comment\">\/\/ Reposition the item<\/span>\r\n            itemElement.style.transform = <span class=\"hljs-string\">`translateX(<span class=\"hljs-subst\">${currentX}<\/span>px)`<\/span>;\r\n          });\r\n        },\r\n        onEnd: <span class=\"hljs-function\"><span class=\"hljs-params\">ev<\/span> =&gt;<\/span> {\r\n          itemElement.style.transition = <span class=\"hljs-string\">'0.2s ease-out'<\/span>;\r\n\r\n          <span class=\"hljs-comment\">\/\/ Fly out the element if we cross the threshold of 150px<\/span>\r\n          <span class=\"hljs-keyword\">if<\/span> (ev.deltaX &lt; <span class=\"hljs-number\">-150<\/span>) {\r\n            <span class=\"hljs-built_in\">this<\/span>.domCtrl.write(<span class=\"hljs-function\">() =&gt;<\/span> {\r\n              itemElement.style.transform = <span class=\"hljs-string\">`translate3d(-<span class=\"hljs-subst\">${windowWidth}<\/span>px, 0, 0)`<\/span>;\r\n            });\r\n            deleteAnimation.play();\r\n\r\n            deleteAnimation.onFinish(<span class=\"hljs-keyword\">async<\/span> () =&gt; {\r\n              <span class=\"hljs-built_in\">this<\/span>.myArray = <span class=\"hljs-built_in\">this<\/span>.myArray.filter(<span class=\"hljs-function\"><span class=\"hljs-params\">number<\/span> =&gt;<\/span> <span class=\"hljs-built_in\">number<\/span> != i + <span class=\"hljs-number\">1<\/span>);\r\n\r\n              <span class=\"hljs-keyword\">const<\/span> toast = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-built_in\">this<\/span>.toastCtrl.create({\r\n                message: <span class=\"hljs-string\">`Item <span class=\"hljs-subst\">${i + <span class=\"hljs-number\">1<\/span>}<\/span> removed.`<\/span>,\r\n                duration: <span class=\"hljs-number\">2000<\/span>\r\n              });\r\n              toast.present();\r\n            });\r\n          } <span class=\"hljs-keyword\">else<\/span> {\r\n            <span class=\"hljs-comment\">\/\/ Fly the item back into the original position<\/span>\r\n            <span class=\"hljs-built_in\">this<\/span>.domCtrl.write(<span class=\"hljs-function\">() =&gt;<\/span> {\r\n              itemElement.style.transform = <span class=\"hljs-string\">''<\/span>;\r\n            });\r\n          }\r\n        }\r\n      }, <span class=\"hljs-literal\">true<\/span>);\r\n\r\n      <span class=\"hljs-comment\">\/\/ Don't forget to enable!<\/span>\r\n      swipeGesture.enable(<span class=\"hljs-literal\">true<\/span>);\r\n    }\r\n  }\r\n\r\n}\r\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\u00a0<code>DomController<\/code>\u00a0again to shift the item out of the view \u2013 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\u00a0<code>onFinish<\/code>\u00a0callback 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\u2019s actually kinda fun to create these kinds of gesture and animation combinations, and if you want another example check out my popular\u00a0<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\u2019s 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\u00a0<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\u00a0<strong>src\/app\/modal-animation.ts<\/strong>\u00a0and insert:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { Animation, createAnimation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> modalEnterAnimation = (\r\n    baseEl: HTMLElement,\r\n    presentingEl?: HTMLElement,\r\n  ): <span class=\"hljs-function\"><span class=\"hljs-params\">Animation<\/span> =&gt;<\/span> {\r\n\r\n\r\n  <span class=\"hljs-keyword\">const<\/span> backdropAnimation = createAnimation()\r\n    .addElement(baseEl.querySelector(<span class=\"hljs-string\">'ion-backdrop'<\/span>)!)\r\n    .fromTo(<span class=\"hljs-string\">'opacity'<\/span>, <span class=\"hljs-number\">0.01<\/span>, <span class=\"hljs-string\">'var(--backdrop-opacity)'<\/span>)\r\n    .beforeStyles({\r\n      <span class=\"hljs-string\">'pointer-events'<\/span>: <span class=\"hljs-string\">'none'<\/span>\r\n    })\r\n    .afterClearStyles([<span class=\"hljs-string\">'pointer-events'<\/span>]);\r\n\r\n  <span class=\"hljs-keyword\">const<\/span> wrapperAnimation = createAnimation()\r\n    .addElement(baseEl.querySelectorAll(<span class=\"hljs-string\">'.modal-wrapper, .modal-shadow'<\/span>)!)\r\n    .beforeStyles({ <span class=\"hljs-string\">'opacity'<\/span>: <span class=\"hljs-number\">1<\/span> })\r\n    .keyframes([\r\n        { offset: <span class=\"hljs-number\">0<\/span>, transform: <span class=\"hljs-string\">'translateY(-100vh)'<\/span> },\r\n        { offset: <span class=\"hljs-number\">0.4<\/span>, transform: <span class=\"hljs-string\">'translateY(20vh)'<\/span>},\r\n        { offset: <span class=\"hljs-number\">0.7<\/span>, transform: <span class=\"hljs-string\">'translateY(-10vh)'<\/span>},\r\n        { offset: <span class=\"hljs-number\">1<\/span>, transform: <span class=\"hljs-string\">'translateY(0vh)'<\/span>},\r\n      ]);\r\n\r\n  <span class=\"hljs-keyword\">const<\/span> baseAnimation = createAnimation()\r\n    .addElement(baseEl)\r\n    .easing(<span class=\"hljs-string\">'ease-out'<\/span>)\r\n    .duration(<span class=\"hljs-number\">900<\/span>)\r\n    .addAnimation([wrapperAnimation, backdropAnimation]);\r\n\r\n  <span class=\"hljs-keyword\">return<\/span> baseAnimation;\r\n};\r\n\r\n<\/code><\/pre>\n<p>This animation will show the backdrop like the regular modal appear, but then somehow\u00a0<em>bounce<\/em>\u00a0in the next page. I\u2019m 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\u2019s simply use it directly when presenting a modal. This is really just passing in your exported\u00a0<code>modalEnterAnimation<\/code>\u00a0to the\u00a0<code>enterAnimation<\/code>\u00a0of the modal like this:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { Component } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { ModalController } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { modalEnterAnimation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/modal-animation'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { MyModalPage } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/my-modal\/my-modal.page'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage {\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> modalCtrl: ModalController<\/span>) { }\r\n\r\n  <span class=\"hljs-keyword\">async<\/span> presentModal() {\r\n    <span class=\"hljs-keyword\">const<\/span> modal = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-built_in\">this<\/span>.modalCtrl.create({\r\n      component: MyModalPage,\r\n      showBackdrop: <span class=\"hljs-literal\">true<\/span>,\r\n      backdropDismiss: <span class=\"hljs-literal\">true<\/span>,\r\n      enterAnimation: modalEnterAnimation,\r\n      cssClass: <span class=\"hljs-string\">'custom-modal'<\/span>\r\n    });\r\n\r\n    <span class=\"hljs-keyword\">await<\/span> modal.present();\r\n  }\r\n}\r\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\u00a0<strong>src\/global.scss<\/strong>:<\/p>\n<pre><code class=\"language-css hljs\"><span class=\"hljs-selector-class\">.custom-modal<\/span> {\r\n    .modal-wrapper {\r\n        <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">80%<\/span>;\r\n        <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">80%<\/span>;\r\n    }\r\n}\r\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\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-modal-enter.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/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\u00a0<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\u2019s say we want to simply fade our pages instead of the regular transition. In that case, we can create a new file at\u00a0<strong>src\/app\/nav-animation.ts<\/strong>\u00a0and check for the\u00a0<code>direction<\/code>\u00a0property of the options to create the right animation order for our elements:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { Animation, createAnimation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> enterAnimation = (baseEl: HTMLElement, opts?: <span class=\"hljs-built_in\">any<\/span>): <span class=\"hljs-function\"><span class=\"hljs-params\">Animation<\/span> =&gt;<\/span> {\r\n    <span class=\"hljs-keyword\">const<\/span> DURATION = <span class=\"hljs-number\">1000<\/span>;\r\n\r\n    <span class=\"hljs-keyword\">if<\/span> (opts.direction === <span class=\"hljs-string\">'forward'<\/span>) {\r\n        <span class=\"hljs-comment\">\/\/ Fade in the next page<\/span>\r\n        <span class=\"hljs-keyword\">return<\/span> createAnimation()\r\n        .addElement(opts.enteringEl)\r\n        .duration(DURATION)\r\n        .easing(<span class=\"hljs-string\">'ease-in'<\/span>)\r\n        .fromTo(<span class=\"hljs-string\">'opacity'<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>);\r\n    } <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-keyword\">if<\/span> (opts.direction === <span class=\"hljs-string\">'back'<\/span>) {\r\n        <span class=\"hljs-comment\">\/\/ Fade in the previous page<\/span>\r\n        <span class=\"hljs-keyword\">const<\/span> rootAnimation = createAnimation()\r\n        .addElement(opts.enteringEl)\r\n        .duration(DURATION)\r\n        .easing(<span class=\"hljs-string\">'ease-out'<\/span>)\r\n        .fromTo(<span class=\"hljs-string\">'opacity'<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>);\r\n\r\n        <span class=\"hljs-comment\">\/\/ Fade out the current top page<\/span>\r\n        <span class=\"hljs-keyword\">const<\/span> leavingAnim = createAnimation()\r\n        .addElement(opts.leavingEl)\r\n        .duration(DURATION)\r\n        .easing(<span class=\"hljs-string\">'ease-out'<\/span>)\r\n        .fromTo(<span class=\"hljs-string\">'opacity'<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>);\r\n\r\n        <span class=\"hljs-comment\">\/\/ Chain both animations<\/span>\r\n        <span class=\"hljs-keyword\">return<\/span> createAnimation().addAnimation([rootAnimation, leavingAnim]);\r\n    }\r\n};\r\n\r\n<\/code><\/pre>\n<p>But as you can see after a few examples \u2013 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\u00a0<a href=\"https:\/\/ionicframework.com\/docs\/angular\/config#config-options\">config object of your Ionic app<\/a>\u00a0like this:<\/p>\n<pre><code class=\"language-ts hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { enterAnimation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/nav-animation'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@NgModule<\/span>({\r\n  declarations: [AppComponent],\r\n  entryComponents: [],\r\n  imports: [BrowserModule, IonicModule.forRoot({\r\n    navAnimation: enterAnimation <span class=\"hljs-comment\">\/\/ Add your animations!<\/span>\r\n  }), AppRoutingModule],\r\n  providers: [\r\n    StatusBar,\r\n    SplashScreen,\r\n    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }\r\n  ],\r\n  bootstrap: [AppComponent]\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> AppModule { }\r\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 hljs typescript\"><span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> router: Router<\/span>) { }\r\n\r\nnavigateToPage() {\r\n  <span class=\"hljs-built_in\">this<\/span>.router.navigateByUrl(<span class=\"hljs-string\">'my-modal'<\/span>);\r\n}\r\n<\/code><\/pre>\n<p>If that\u2019s too much for you and you just need a decent animation in\u00a0<em>some<\/em>\u00a0places of your app, you can also use the Ionic\u00a0<code>NavController<\/code>\u00a0to define the animation for\u00a0<strong>the next transition<\/strong>!<\/p>\n<p>That means, calling\u00a0<code>setDirection()<\/code>\u00a0won\u2019t 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 hljs typescript\"><span class=\"hljs-keyword\">import<\/span> { Component } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/core'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { Router } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/router'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { NavController } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@ionic\/angular'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> { enterAnimation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/nav-animation'<\/span>;\r\n\r\n<span class=\"hljs-meta\">@Component<\/span>({\r\n  selector: <span class=\"hljs-string\">'app-home'<\/span>,\r\n  templateUrl: <span class=\"hljs-string\">'home.page.html'<\/span>,\r\n  styleUrls: [<span class=\"hljs-string\">'home.page.scss'<\/span>],\r\n})\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> HomePage {\r\n\r\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> router: Router, <span class=\"hljs-keyword\">private<\/span> navCtrl: NavController<\/span>) { }\r\n\r\n  navigateToPage() {\r\n    <span class=\"hljs-comment\">\/\/ Define the animation for the transition!<\/span>\r\n    <span class=\"hljs-built_in\">this<\/span>.navCtrl.setDirection(<span class=\"hljs-string\">'forward'<\/span>, <span class=\"hljs-literal\">true<\/span>, <span class=\"hljs-string\">'forward'<\/span>, enterAnimation);\r\n    <span class=\"hljs-built_in\">this<\/span>.router.navigateByUrl(<span class=\"hljs-string\">'my-modal'<\/span>);\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>Now we have completely changed the transition between two pages:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter jetpack-lazy-image jetpack-lazy-image--handled\" style=\"max-width: 40%; min-width: 40%; margin: 0 auto; display: block;\" src=\"https:\/\/ionicframework.com\/blog\/wp-content\/uploads\/2020\/12\/ionic-custom-nav-transition.gif\" alt=\"\" data-lazy-loaded=\"1\" \/><\/p>\n<p>It\u2019s 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\u00a0<a href=\"https:\/\/ionicacademy.com\/\">join the Ionic Academy<\/a>\u00a0and get access to a ton of learning material to boost your Ionic development skills.<\/p>\n<p>And don\u2019t forget to\u00a0<a href=\"https:\/\/www.youtube.com\/user\/saimon1924\">subscribe to my YouTube channel<\/a>\u00a0for fresh Ionic tutorials coming every week!<\/p>\n<p>The post <a href=\"https:\/\/ionicframework.com\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\/\" rel=\"nofollow\">Building Interactive Ionic Apps with Gestures and Animations<\/a> appeared first on <a href=\"https:\/\/ionicframework.com\/blog\" rel=\"nofollow\">Ionic Blog<\/a>.<\/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":53,"featured_media":2576,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[449],"tags":[451,452,450],"class_list":["post-2575","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ionic-apps","tag-animation-to-ionic-apps","tag-applying-gestures-to-ionic-apps","tag-building-ionic-apps"],"acf":{"custom_meta_title":"Building Interactive Ionic Apps using Gestures and Animations","meta_description":"Do you know, how to apply gestures and animations to Ionic Apps ? Go through this article to know about gestures and animations in Ionic App.","meta_keyword":"building ionic apps, applying gestures to ionic apps, applying animation to ionic apps, gesture utility api, animation utility api","other_meta_tag":"<meta property=og:locale content=\"en-IN\" \/>\r\n<meta property=og:type content=\"website\" \/>\r\n<meta property=og:title content=\"Building Interactive Ionic Apps with Gestures and Animations\"\/>\r\n<meta property=og:description content=\"Do you know, how to apply gestures and animations to Ionic Apps ? Go through this article to know about gestures and animations in Ionic App.\"\/>\r\n<meta property=\"og:image\" content=\"https:\/\/ntspl.co.in\/blog\/wp-content\/uploads\/2020\/12\/Ionic-Apps-with-Gestures-and-Animations.jpg\"\/>\r\n<meta property=og:url content=\"https:\/\/www.ntspl.co.in\/blog\/building-interactive-ionic-apps-with-gestures-and-animations\"\/>\r\n<meta property=og:site_name content=NTSPL \/>\r\n<meta name=\"twitter:site\" content=\"@NTSPL\">\r\n<meta name=twitter:card content=\"summary\" \/>\r\n<meta name=twitter:description content=\"Do you know, how to apply gestures and animations to Ionic Apps ? Go through this article to know about gestures and animations in Ionic App.\"\/>\r\n<meta name=twitter:title content=\"Building Interactive Ionic Apps with Gestures and Animations\"\/>"},"_links":{"self":[{"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/posts\/2575"}],"collection":[{"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/comments?post=2575"}],"version-history":[{"count":7,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/posts\/2575\/revisions"}],"predecessor-version":[{"id":6469,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/posts\/2575\/revisions\/6469"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/media\/2576"}],"wp:attachment":[{"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/media?parent=2575"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/categories?post=2575"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ntspl.co.in\/blog\/wp-json\/wp\/v2\/tags?post=2575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}