55
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

laravel5.5 jTinderを使ってスワイプ機能 (マッチングアプリ)

Last updated at Posted at 2021-12-13

はじめに

DMM WEBCAMP Advent Calendar 2021 :snowman2:の14日目を担当させて頂く、yuukaです!(о´∀`о)

個人開発でマッチングアプリを作成した際にボタンのクリックだけでなく
スマホアプリのような滑らかなスワイプだったらかっこいいな〜
と考えて、実装した時のことを書いていこうと思います。

今回はjTinderを使って滑らかなスワイプを実装し、ajax通信でDBに値を保存していきす。☺️

プレビュー

以下が完成イメージです。
Image from Gyazo

前提

  • laravel5.5を使用
  • laravelの環境構築を終えている
  • DBとの接続を終えている
  • 新規登録、ログインの実装を終えている

実装手順

1.ER図を確認する
2.新規登録での画像アップロード機能
3.jTinderの導入
4.viewを作成
5.jQueryの記述
6.jQueryの説明
7.DBを確認してみる

#1.ER図を確認する

今回、マッチングの実装には触れずにスワイプの部分の実装になるのですが
イメージしやすいように全体のER図を作成しました。

マッチングはユーザ同士の繋がりになるので、多対多の関係です。
そのため、ここで作成しているMatchテーブルは、中間テーブルになります。
Image from Gyazo
Matchテーブルには、3つのカラムがあります。

カラム名
from_user_id いいな,イマイチだなと判断するユーザのid (FK)  
to_user_id いいな,イマイチだなと判断されるユーザのid (FK)
is_like いいなと思って貰えるとtrue、イマイチだとfalseをDBに保存  

#2. 新規登録での画像アップロード機能

マッチングアプリですので、新規登録時に画像を登録する必要があります。

今回、新規登録での画像アップロード機能の実装は省略しています。
まだの方は先にそちらの実装からお願いします。

以下のサイトは、とても分かりやすかったです。

#3. jTinderの導入
公式ドキュメント

1.公式のドキュメント内のjTinder.cssから必要なcssの部分をコピーする

公式のドキュメントで使用している画像は必要ないよ。
という方は、以下のようなコードはコピーしなくて大丈夫です。
可読性を高めるために、必要のないコードは省いていきましょう。

css/jTinder.css
/* jTinder images */
#tinderslide .pane5 .img {
    background: url("../img/pane/pane5.jpg") no-repeat scroll center center;
    background-size: cover;
}
#tinderslide .pane4 .img {
    background: url("../img/pane/pane4.jpg") no-repeat scroll center center;
    background-size: cover;
}

~省略~

2.resources/assets/sassの配下に_jTinder.scssを作成

以下のような配置になっていれば、大丈夫です。
そして、作成した_jTinder.scssの中に1.でコピーした内容を貼り付けましょう。
Image from Gyazo
3.作成した_jTinder.scssをapp.scssでimportする

resources/assets/sass/app.scss
  // Variables
  @import "variables";
+ @import "jTinder";

4.jsも同じように作業

公式のドキュメントの
js/jquery.jTinder.jsjs/jquery.transform2d.jsの中身をコピーします。

resources/assets/jsの配下に
jquery.jTinder.jsjquery.transform2d.jsを作成します。

以下のような配置になっていれば、大丈夫です。
Image from Gyazo
5.作成した2つのファイルをapp.jsでrequireする

resources/assets/js/app.js
  require('./bootstrap');
+ require('./jquery.jTinder');
+ require('./jquery.transform2d');

#4. viewを作成

まずは、resources/views/usersの中にindex.blade.phpを作成します。
@foreachを使用し、ユーザーの表示画面を実装していきます。

1行目に書かれているid="tinderslide"でjsが発火。
4行目のdata-user_id="{{ $user->id }}"でユーザのidを送っています。
この2箇所を書き忘れないようにしましょう。

resources/views/users/index.blade.php
<div id="tinderslide">
    <ul>
        @foreach ($users as $user)
        <li data-user_id="{{ $user->id }}">
            <img src="{{ Storage::url($user->image) }}" />
            <div class="like">
                <img src="{{ asset('images/like.png')}}" alt="like" />
            </div>
            <div class="dislike">
                <img src="{{ asset('images/nope.png')}}" alt="dislike" />
            </div>
        </li>
        @endforeach
    </ul>

        ~省略~

ポイントはlikeクラスdislikeクラスです。
このクラスを呼び出すとプレビューのように顔写真の上に
LIKEやNOPEの画像をかっこよく表示してくれます。
今回、オリジナルの画像を使用していますが、icon, Font Awesomeなどを活用しても可愛いと思います!😊

表示する位置などを変更したい場合はjTinder.cssの以下のコードを編集しましょう。

該当のcssコード
resources/assets/sass/_jTinder.scss
/* Like & dislike badge images */
#tinderslide .like,
#tinderslide .dislike {
  opacity: 0;
  height: 80px;
  position: absolute;
  width: 170px;
  left: 45px; 
  top:40px;
  z-index: 1;
  overflow: hidden;
  -webkit-transform: translate3d(0%,0,0) scale3d(1,1,1);
  -moz-transform: translate3d(0%,0,0) scale3d(1,1,1);
  -ms-transform: translate3d(0%,0,0) scale3d(1,1,1);
  -o-transform: translate3d(0%,0,0) scale3d(1,1,1);
  transform: translate3d(0%,0,0) scale3d(1,1,1);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

#5. jQueryの記述

まだまだ、リファクタリングできると思いますので、アドバイス頂けると嬉しいです。
次の章で詳しく説明していきたいと思います。

$("#tinderslide").jTinder({
    onDislike: function (user) {
        let user_id = user[0].dataset.id;
        postMatch(user_id, 0)
    },
    onLike: function (user) {
        let user_id = user[0].dataset.id;
        postMatch(user_id, 1)
    }
});

let postMatch = function (user_id, is_like) {
    $.ajax({
        type: "post",
        url: "/users",
        headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
        data: {
            to_user_id: user_id,
            is_like: is_like,
        },
    }).then((res) => {
        console.log(res);
    }).fail((error) => {
        console.log(error.statusText);
    });
};

#6. jQueryの説明

$("#tinderslide").jTinder({
    onDislike: function (user) {
        let user_id = user[0].dataset.id; // $user->id が取得できる
        postMatch(user_id, 0)
    },
    onLike: function (user) {
        let user_id = user[0].dataset.id;
        postMatch(user_id, 1)
    }
});

~省略~

初めに、1行目の記述によって発火します。

そして、viewを作成で記述した<li data-id="{{ $user->id }}">
送った値は、datasetの中のidに入ります。
今回は、引数をuserと指定しているため、user[0].dataset.idで値が取得できます。

$("#tinderslide").jTinder({
    onDislike: function (user) {
      //
    },
    onLike: function (user) {    
      //
    },

左にスワイプさせると2行目のonDislike:
右にスワイプさせると5行目のonLike:に飛びます。
この部分の仕組みが気になる方は、jquery.jTinder.jsの記述を調べてみてください。

onLike: function (user) {
        let user_id = user[0].dataset.id;
        postMatch(user_id, 1)
    },

今回は、onLikeの中身を詳しく見ていきます。
1行目の function (user) {で引数をuserと指定しています。
ここがitemだった場合、item[0].dataset.idになります。

2行目でuser[0].dataset.iduser_idに代入しています。

3行目でpostMatchという関数を呼びだしています。
そして、2つの引数を送っています。
1つ目はuser_id、2つ目はis_like(boolean型)の値を送っています。
onLikeだと1onDislikeだと0を引数に設定しています。
0 ... false
1 ... true

続いて、postMatchという関数について説明していきたいと思います。
この関数の中で、ajax通信を行っています。

const postMatch = function (user_id, is_like) {
};

先ほどのpostMatch(user_id, 1)
第一引数と第二引数の(user_id, is_like)に入ります。

次に、ajax通信の書き方になります。

LaravelでajaxのPOST送信を行うときは、上の4行目で記述しているように
CSRFトークンを追加する必要があります。
忘れてしまうと419エラーなどが起きてしまいます。

$.ajax({
    type: "post", // dbに新規登録するのでpostと指定
    url: "/users", // 保存する記述をしているコントローラーのurlを指定
    headers: { // CSRFトークンを追加
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    },
    data: { // 左側にカラム名、右側に保存したいデータ
        to_user_id: user_id,
        is_like: is_like,
    },
}).then((res) => {
    console.log(res);
}).fail((error) => {
    console.log(error.statusText);
});

ajax通信が終わり、dbに保存が成功した時は.then
どこかで予期せぬエラーが起きてしまった時は.failにとぶように設定します。

#7. DBを確認してみる
スワイプした後にデータがきちんと入っているか確認してみましょう。
is_likeのtureかfalseの判定が間違えていないかもチェックしてみてください。
Image from Gyazo

終わりに

今回は、laravelというよりもjQueryがメインになってしまいました😔
ajax通信やjTinderは、初めての実装だったので楽しかったです!
ぜひ、参考にしてもらえたら嬉しいです😳
今回は、マッチング機能には触れていないのでルーティングやコントローラーの記述は省略しています。
参考文献のYoutubeがとてもわかりやすく説明してくださっているので、実装したいな!と思った方はのぞいてみてください💁

参考文献

この記事は以下の情報を参考にして執筆しました。
jTinderについての実装

マッチングアプリの要件や実装の考え方

55
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?