Bonjour à tous! Dans ce tutoriel Ionic Tinder nous allons voir comment recréer le Swipe de Tinder avec Ionic et Angular.

Cette fonctionnalité est en effet de plus en plus répandu dans les applications de rencontre (Shapr, Yubo, Meetic, etc).

Si vous avez un projet d’application réseau social ou de rencontre, suivez attentivement ce tutoriel très simple vous allez le voir.

Nous utiliserons différents packages et frameworks, notamment ng-swipe-card et HammerJS.

Ce tutoriel est réalisé avec les frameworks Ionic et Angular, car il existe d’autre module préconçu du Swipe Tinder pour les autres frameworks.

Ionic Tinder Swipe
Ionic Tinder Swipe

Pour créer notre application Ionic Tinder Swipe, nous allons suivre les étapes suivantes:

  1. Installer le package ng-swipe-card et HammerJS
  2. Recréer le design de Tinder avec Ionic
  3. Reproduire les cartes de Tinder
  4. Faire glisser nos cartes à droite ou à gauche
  5. Swiper avec les boutons
  6. Récupérer les résultats de nos swipes

Comment installer les packages dans Ionic pour créer le swipe Tinder ?

Pour commencer je vous invite à créer une application Ionic de type vierge avec le framework Angular:

ionic start tinder blank --type=angular

Notre fonctionnalité de swipe sera concentré sur une seule et même page où nous pourrons aussi consulter nos résultats.

Cette application est principalement basée sur le package ng-swipe-card dont je vous laisse la documentation.

Ce package est lui-même basé sur la bibliothèque Hammer.JS spécialisée dans la gestion des interactions des applications web.

Vous pouvez donc commencer par installer le package ng-swipe-card dans votre application Ionic:

npm install ng-swipe-card --save

Puis d’installer également la bibliothèque Hammer JS dans votre projet Ionic:

npm install hammerjs --save

La bibliothèque Hammer JS est très simple à prendre en main et s’installe aussi très facilement dans les applications web.

Le seul élément à configurer se situe dans le fichier suivant:

src/main.ts

Dans lequel vous devez ajouter la ligne d’importation suivante pour utiliser la bibliothèque Hammer JS:

import 'hammerjs';

En ce qui concerne le package ng-swipe-card, son utilisation est également très simplifiée, puisque nous n’avons pas à le déclarer globalement dans l’application.

Vous n’avez qu’à vous rendre dans le fichier module de la page où le package sera utilisé, ici la page Home:

src/app/home/home.module.ts

Puis à importer puis déclarer le package dans votre tableau imports[]:

import { SwipeCardLibModule } from 'ng-swipe-card';

@NgModule({
  imports: [
    CommonModule,
    [...]
    SwipeCardLibModule,

Nous avons donc installé et configuré le package et la bibliothèque dont nous allons avoir besoin.

Passons maintenant à l’apparence rapide de notre application Ionic pour qu’elle ressemble un peu plus à Tinder.

Commencez le développement mobile avec Ionic et Firebase
Commencez le développement mobile avec Ionic et Firebase

Comment recréer avec Ionic le design de Tinder ?

On commence le développement de notre application avec le rapide design de Tinder avec Ionic.

En haut de notre page, nous retrouvons le classique header de l’application Tinder:

Ionic Tinder Swipe Header

Nous pouvons facilement reproduire un tel design de header avec Ionic, en utilisant au maximum ses composants:

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-button fill="clear" color="medium">
        <ion-icon slot="icon-only" name="settings-sharp"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title>
      <img class="logo" src="../../assets/tinder-logo.png">
    </ion-title>
    <ion-buttons slot="end">
      <ion-button fill="clear" color="medium">
        <ion-icon slot="icon-only" name="chatbubbles-sharp"></ion-icon>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

N’oubliez pas de télécharger l’image du logo de marque de Tinder ci-dessous (à placer dans le dossier assets/):

Ionic Tinder Logo

Et de déclarer ensuite dans votre fichier CSS, la classe de notre logo auquel nous donnons une hauteur de 40 pixels:

.logo {
  height: 40px;
}

On enchaîne directement avec les boutons d’actions situés en bas de l’écran.

On traitera les cartes à glisser dans la partie suivante, car nous utiliserons le composants issu du package ng-swipe-card.

Pour le le moment nous créons tout ce qui est indépendant des modules importés, à savoir les quatre boutons situés en bas de notre page:

Ionic Tinder Swipe Buttons

Sur ces quatre boutons, deux seulement seront réellement fonctionnels, à savoir le bouton like ou dislike.

Les deux autres boutons situés aux extrémité sont présents pour reproduire l’interface de Tinder mais ne seront pas traités dans ce tutoriel.

Voilà donc le rendu HTML de mes quatre boutons pour les faire ressembler au maximum à ceux de Tinder avec Ionic:

<div class="button_box">
  <ion-button class="small_button" mode="ios" shape="round" fill="outline" >
    <ion-icon color="warning" name="refresh"></ion-icon>
  </ion-button>
  <ion-button (click)="swipeleft()" mode="ios" class="large_button" shape="round" fill="outline" >
    <ion-icon color="danger" name="close"></ion-icon>
  </ion-button>
  <div class="space"></div>
  <ion-button (click)="swiperight()" mode="ios" class="large_button" shape="round" fill="outline">
    <ion-icon color="success" name="heart"></ion-icon>
  </ion-button>
  <ion-button class="small_button" mode="ios" shape="round" fill="outline">
    <ion-icon color="primary" name="location-sharp"></ion-icon>
  </ion-button>
</div>

Comme d’habitude on utilise les icônes de la bibliothèque officielle d’Ionic disponible aujourd’hui dans sa version 5.

Au niveau du CSS à appliquer à nos boutons, on reste sur quelques chose d’assez simple, mais d’assez détaillé pour ressembler aux maximum à Tinder.

On commence par englober nos quatre dans une boîte flex-box, et on modifie ensuite nos boutons en deux classes: small_button et large_button.

Je reprends ensuite toutes les propriétés CSS des boutons Ionic (comme couleur de la bordure –border-color) que j’édite manuellement.

Voilà donc nos quatre classes CSS (la dernière permet d’ajuster l’espacement entre les boutons):

.button_box {
  width: 90%;
  display: flex;
  align-items: flex-start;
  margin-left: 5%;
  justify-content: center;
}
.small_button {
  font-size: 20px;
  --border-radius: 50%;
  --border-width: 8px;
  --border-color: #f3f3f3;
  --padding-start: 8px;
  --padding-end: 8px;
  --background-activated: #f3f3f3;
}
.large_button {
  font-size: 30px;
  --border-radius: 50%;
  --border-width: 8px;
  --border-color: #f3f3f3;
  --padding-start: 15px;
  --padding-end: 15px;
  margin-right: -10px;
  margin-left: -10px;
  --background-activated: #f3f3f3;
}
.space {
  width: 12px;
}

La première partie de l’apparence de notre application Ionic Tinder est maintenant terminée.

On continue naturellement avec nos cartes à faire glisser pour reproduire le swipe de Tinder.

Créez des applications Ionic à interface sociale avec Firebase
Créez des applications Ionic à interface sociale avec Firebase

Comment recréer avec Ionic les cartes de Tinder ?

Nous allons maintenant créer l’élément central de notre page Ionic Tinder: les cartes à swiper.

Ionic Tinder Swipe Card

Vous devez à présent distinguer plusieurs choses, nous utilisons le package ng-swipe-card qui propose un composant de carte préconçu.

Mais nous allons nous-mêmes désigner l’apparence de nos cartes à swiper. En fin de compte le package ng-swipe-card permet d’accéder à la fonctionnalité de Swiper et au résultat du swipe (true ou false).

Encore une fois, cette interaction avec l’écran est possible grâce à la bibliothèque Hammer JS, qui propose une très grande gamme de gestuelle pour les applications web.

Nous ne faisons dans ce tutoriel que réutiliser des outils mis à disposition par d’autres développeurs.

Pour commencer le travail sur nos cartes, nous créons un tableau contenant différents objets, un pour chaque personne:

avatars = [
  {
    name: 'Donald Trump',
    age: 73,
    image: '../../assets/trump.jpg',
    visible: true
  },
  {
    name: 'Barack Obama',
    age: 58,
    image: '../../assets/obama.jpg',
    visible: true
  },
  {
    name: 'Elon Musk',
    age: 48,
    image: '../../assets/musk.jpg',
    visible: true
  },
  {
    name: 'Jeff Bezos',
    age: 56,
    image: '../../assets/bezos.jpg',
    visible: true
  },
  {
    name: 'Beyonce',
    age: 38,
    image: '../../assets/beyonce.jpg',
    visible: true
  },
  {
    name: 'Eminem',
    age: 47,
    image: '../../assets/eminem.png',
    visible: true
  }
];

Pour chaque personne, on stocke quatre informations:

  • Nom: sous forme de chaîne de caractère
  • Âge: sous forme de nombre
  • Image: en stockant l’adresse de sa photos de profil
  • Visibilité: sous forme de booléen (vrai ou faux) pour masquer les casquer les cartes une fois qu’elles sont swipées

Par défaut toutes les cartes seront visibles mais étant superposées grâce au CSS, on n’en affichera qu’une seule à la fois.

Vous devez également en complément télécharger toutes les photos de profil de vos personnalités (dans le dossier assets/):

Tinder Photo

On passe maintenant à l’affichage de nos cartes dans le HTML, en réutilisant en premier lieu le composant sw-card-wrapper.

Par la suite nous verrons comment utiliser le directive swSwipeable proposée par le package ng-swipe-card.

Je vous montre dès à présent le code final de nos cartes Tinder à swiper, mais nous examiner le code étapes par étapes:

<sw-card-wrapper #cardWrapper>
  <div class="card" *ngFor="let avatar of avatars, let index = index"
       [class.visible]="avatar.visible" [class.hidden]="!avatar.visible"
       swSwipeable
       [width]="350"
       [height]="500"
       [orientation]="'x'"
       (swiped)="swiped($event, index)">
    <img [src]="avatar.image" [alt]="avatar.name">
    <h2>{{avatar.name}}, {{avatar.age}}</h2>
  </div>
</sw-card-wrapper>

L’ensemble de nos cartes sont donc contenu dans le composants sw-card-wrapper que nous avons évoqué précedemment.

Mais la carte individuelle à swiper est représenté par la boîte div avec la classe “card.

Nous effectuons d’ailleurs une boucle for avec la directive *ngFor de notre tableau avatars pour parcourir nos personnalités.

On affiche ensuite les informations de nos avatars avec l’image et le texte situé en dessous:

<img [src]="avatar.image" [alt]="avatar.name">
<h2>{{avatar.name}}, {{avatar.age}}</h2>

Si vous souhaitez apprendre à gérer facilement les directive *ngFor d’Ionic et Angular, je vous conseille fortement mon cours Ionic JS.

On termine cette partie avec les propriétés CSS qui nous permettront de bien disposer nos cartes de manière superposé.

On commencer par donner quelques propriétés à notre composant sw-card-wrapper pour lui donner une certaine hauteur et centrer le contenu qui s’y trouvera:

sw-card-wrapper {
  height: 550px;
  display: flex;
  width: 100%;
  justify-content: center;
  align-items: center;
  z-index: 5;
}

On lui ajoute également la propriété z-index: 5 pour positionner son contenu en haut de notre page, par rapport aux boîtes qui feront office du bas de notre paquet de carte.

Card Effect

En effet en dessous de nos cartes nous afficherons différentes boîtes HTML pour donner un effet de volume à notre paquet de cartes.

On continue maintenant avec les propriétés les plus importantes celle concernant les cartes elles-mêmes.

Pour cela on positionne nos cartes de manière absolu, puis on leur donne le style des cartes Tinder:

.card {
  box-shadow: 0px 1px 3px #e6e6e6;
  border-radius: 10px;
  margin-bottom: 30px;
  overflow: hidden;
  position: absolute;
  background-color: white;
}
.card img{
  height: 450px;
  min-width: 100%;
  max-width: none;
}
.card h2{
  background-color: white;
  font-size: 20px;
  margin: 10px 15px;
}

Avec ce code CSS, nos cartes seront ainsi positionnées au même endroit, et nous n’afficherons qu’une carte à la fois.

C’est tout l’intérêt du swipe qui nous permettra de les faire glisser. Mais attention le swipe ne suffit pas, il nous faudra cacher une carte une fois que celle-ci vient d’être swipé.

Pour cela nous allons utiliser les deux classes CSS suivantes:

.visible {
  display: block;
}
.hidden {
  display: none;
}

Nous allons maintenant voir dans la partie suivante le fonctionnement complet du swipe et sa prise en main.

Apprenez à créer des applications Ionic directement avec Driss AS
Apprenez à créer des applications Ionic directement avec Driss AS

Comment faire glisser nos cartes Ionic comme dans Tinder ?

Reprenons maintenant nos cartes Tinder pour comprendre exactement où se passe le glissement.

Nous utilisons en fait la directive swSwipeable mise à disposition par le package ng-swipe-card, que nous appliquons à notre boîte div card:

<div class="card" swSwipeable [...]>

Cela va rendre notre carte glissable en cliquant et déplaçant tout son contenu.

Nous avons également la possibilité de choisir l’orientation du geste pour swiper, vertical (y) ou horizontal (x).

Pour reprendre l’exemple de Tinder avec Ionic, nous allons permettre le swipe horizontal de nos cartes:

<div class="card" [orientation]="'x'" [...]>

Vos cartes sont maintenant glissable, vers la gauche ou vers la droite. Mais nous avons besoin de déclarer l’évènement associé à ce swipe.

C’est là encore que nous utilisons tout le travail fourni par le package ng-swipe-card.

Il existe en effet l’évènement (swiped) auquel nous associons la fonction swiped() du même nom que nous allons déclarer juste après.

<div class="card" (swiped)="swiped($event, index)" [...]>

Nous associons également à cette fonction deux paramètres:

  1. le résultat du swipe $event (true ou false)
  2. le numéro de la carte swipée index (sa position dans la liste)

En effet lorsque nous parcourons notre tableau avatars avec la directive ngFor, nous comptons également le nombre d’objets rencontré avec la variable index:

<div class="card" *ngFor="let avatar of avatars, let index = index" [...]>

Nous sommes donc de cette manière capable de déclarer la fonction swiped() pour afficher par exemple dans la console le résultat du swipe:

swiped(event: any, index: number) {
  console.log(this.avatars[index].name + ' swiped ' + event);
}

Si ce test fonctionne bien, vous afficherez par exemple dans la console “Eminem swiped false“.

Ce que nous voulons faire en complément de notre swipe est de cacher la carte venant d’être swipé.

Pour cela nous allons récupérer le numéro de l’avatar en question (stocké dans la variable index) et nous allons modifier le champ visible.

On reprend donc le tableau avatars et change le champ visible de la personnes concernée:

this.avatars[index].visible = false;

Voilà donc votre fonction swiped() pour le moment:

swiped(event: any, index: number) {
  console.log(this.avatars[index].name + ' swiped ' + event);
  this.avatars[index].visible = false;
}

Comment swiper les cartes avec boutons ?

Nous souhaitons maintenant ajouter la possibilité de swiper manuellement ou en cliquant concrètement sur un bouton pour swiper une personne.

Nous avons déjà créé nos deux boutons par le passé pour proposer de liker ou disliker une personne, mais nous n’avons pas encore déclaré leurs fonctions.

<ion-button (click)="swipeleft()" mode="ios" class="large_button" shape="round" fill="outline" >
  <ion-icon color="danger" name="close"></ion-icon>
</ion-button>
<div class="space"></div>
<ion-button (click)="swiperight()" mode="ios" class="large_button" shape="round" fill="outline">
  <ion-icon color="success" name="heart"></ion-icon>
</ion-button>

Pour commencer nous devons déclarer une nouvelle variable pour stocker l’indice de la carte actuellement affichée.

Nous appelons cette variable currentIndex:

currentIndex: number;

Nous parcourons dans notre HTML tout notre tableau avatar, la carte placé en haut de la pile aura donc l’indice le plus élevé.

Et comme le tableau contient la position dite [0], nous pouvons donner l’indice de départ avec la longueur du tableau moins un:

constructor() {
  this.currentIndex = this.avatars.length - 1;
  console.log(this.currentIndex);
}

De cette manière je peux par déclarer la première fonction swipeleft() pour rendre la carte actuellement présenté invisible:

swipeleft() {
  this.avatars[this.currentIndex].visible = false;
  this.currentIndex--;
}

Je peux faire de même pour le bouton like, avec la fonction swiperight() car pour le moment nous ne récupérons pas le résultat du swipe:

swiperight() {
  this.avatars[this.currentIndex].visible = false;
  this.currentIndex--;
}

N’oubliez pas cependant d’enlever une unité lorsque l’on swipe la carte manuellement avec le geste de swipe:

swiped(event: any, index: number) {
  console.log(this.avatars[index].name + ' swiped ' + event);
  this.avatars[index].visible = false;
  this.currentIndex--;
}

Voyons maintenant pour finir comment récupérer les résultats de nos swipes.

Comment récupérer les résultats des Swipes Tinder ?

Swipe Result

On commence par créer un nouveau tableau dans lequel nous allons ajouter au fur et à mesure des informations:

results = [];

Je créé ensuite rapidement une liste d’item dans laquelle je parcours le tableau results (vide au début):

 <ion-item  *ngFor="let result of results">
   <ion-label>{{ result }}</ion-label>
</ion-item>

Je contient ensuite cette liste dans différentes boîte pour afficher ce résultat en dessous de nos cartes:

<div class="card_bg_box">
  <div class="card_bg_1">
    <ion-item  *ngFor="let result of results">
      <ion-label>{{ result }}</ion-label>
    </ion-item>
  </div>
  <div class="card_bg_2"></div>
</div>

Je donne ensuite un certain nombre de propriétés CSS pour positionner cette boîte absolue juste en dessous de nos cartes Tinder:

.card_bg_box {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.card_bg_1 {
  position: absolute;
  box-shadow: 0px 1px 4px #cecece;
  background-color: white;
  height: 481px;
  width: 340px;
  top: 50px;
  border-radius: 10px;
  z-index: 1;
}
.card_bg_2 {
  position: absolute;
  box-shadow: 0px 1px 4px #cecece;
  background-color: white;
  height: 481px;
  width: 330px;
  top: 55px;
  border-radius: 10px;
  z-index: 0;
}

Passons pour conclure sur le stockage de données de notre tableau results. Nous devons en effet récupérer le résultat de chaque swipe ayant été effectué.

Pour cela nous pouvons ajouter dans la fonction swiped() le résultat que nous affichions précédemment dans la console à notre tableau results:

this.results.push(this.avatars[index].name + ' swiped ' + event);

De cette façon on va stocker dans le tableau les résultats sous la forme “Donald Trump swiped false”.

La fonction swiped() finale ressemble donc à cela:

swiped(event: any, index: number) {
  console.log(this.avatars[index].name + ' swiped ' + event);
  this.avatars[index].visible = false;
  this.results.push(this.avatars[index].name + ' swiped ' + event);
  this.currentIndex--;
}

Dans les cas où nous utilisons les boutons pour swiper nos cartes, le principe est casiment le même.

Simplement ici on ne récupère pas d’évènement et de résultat true ou false, on ajuste en fonction de la fonction à exécuter.

Par exemple pour la fonction swipeleft() donc un dislike, on ajoute directement:

this.results.push(this.avatars[this.currentIndex].name + ' swiped false');

Ainsi pour la fonction swiperight() on ajouter ‘swiped true’. Voilà donc le résultat final de nos deux fonctions:

swipeleft() {
  this.avatars[this.currentIndex].visible = false;
  this.results.push(this.avatars[this.currentIndex].name + ' swiped false');
  this.currentIndex--;
}

swiperight() {
  this.avatars[this.currentIndex].visible = false;
  this.results.push(this.avatars[this.currentIndex].name + ' swiped true');
  this.currentIndex--;
}

Conclusion

Vous pouvez pour gagner du temps télécharger le code source complet de l’application et le reprendre.