無限に連打できるいいねボタンなので実装するにはもうちょっと手を加えないといけないんですが、 いいねボタンを押すとデータベースとやり取りして値がリアルタイムに更新されて返ってくるという機能がすごく簡単に出来た。
Firebaseを初めて扱ったので、その練習と覚書。
制限あっても無料のSparkプランで十分に使えるのがいいですね。
Like Button Using JavaScript and Firebase
の記事とだいたい一緒なんですが、Javascript SDK v8からv9に上がって記事内にあるコードでは動かないのでちょっと修正しています。あとFirebase Authentication で匿名認証を追加しています。
アカウント取得とプロジェクトの作成
Googleアカウントを持っていたらすぐに始められます。
プロジェクトは作成済とします。
index.html を作成
HTML code
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet" />
<title>Count Likes</title>
</head>
<!--CSS code-->
<body>
<div class="CountLike" id="count-1">
<button class="button button1"><i class="fa fa-heart"></i> Like <span class="counterStat">...</span></button>
</div>
<div class="CountLike" id="count-2">
<button class="button button1"><i class="fa fa-heart"></i> Like <span class="counterStat">...</span></button>
</div>
<!--Javascript Code-->
</body>
</html>
データ構造
いいねボタンを同一ページ内に複数配置しているので、idを取得して階層を作ることにした。イメージはこんな感じ。
{
"count-1": {
"likes": value
},
"count-2": {
"likes": value
}
}
いいねボタンの下にlikes以外のkeyは持たないことにする。
ユーザーの情報を取得するなら、もっとちゃんと考えないといけないだろうし……。
for Firebase code
初期化
まずはJavascript SDKをCDNから読み込み。npm推奨されてるけども。
参考:JavaScriptプロジェクトにFirebaseを追加する別の方法
そして firebaseConfig
に作成したFirebaseプロジェクト設定を記入してinitializeApp()
で初期化します。
databaseとauthも使用するのでそれらも追加。
</body>
の前で読み込みます。
<script type="module">
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.12.1/firebase-app.js'
// Add Firebase products that you want to use
// https://firebase.google.com/docs/web/alt-setup
import { getDatabase, ref, child, runTransaction, onValue } from 'https://www.gstatic.com/firebasejs/9.12.1/firebase-database.js'
import { getAuth, signInAnonymously, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/9.12.1/firebase-auth.js'
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "Paste Your API Key provided by Firebase",
authDomain: "Paste Your authDomain provided by Firebase",
projectId: "Paste Your projectId provided by Firebase",
databaseURL: "Create a database and then paste the url of that database here",
storageBucket: "Paste Your storageBucket provided by Firebase",
messagingSenderId: "Paste Your messagingSenderId provided by Firebase",
appId: "Paste Your appId provided by Firebase"
};
const app = initializeApp(firebaseConfig);
const database = getDatabase();
const auth = getAuth();
</script>
匿名認証
Firebase Authentication も有効にします。今回は匿名認証で。
参考:JavaScript を使用して Firebase 匿名認証を行う
// Authenticate with Firebase Anonymously Using JavaScript
// https://firebase.google.com/docs/auth/web/anonymous-auth?hl=ja
signInAnonymously(auth).catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.error(errorCode, errorMessage)
});
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
const uid = user.uid;
const dbRef = ref(getDatabase());
// Like Counter
const dCounters = document.querySelectorAll('.CountLike');
[].forEach.call(dCounters, function(dCounter) {
let cId = dCounter.id;
// get firebase data
onValue(child(dbRef, "/" + cId + "/likes"), (snapshot) => {
let data = snapshot.val() || 0;
dCounter.querySelector('span').innerHTML = data;
});
// set firebase data
dCounter.querySelector('button').addEventListener('click', function() {
runTransaction(child(dbRef, "/" + cId + "/likes"), (dCount) => {
return (dCount || 0) + 1;
});
});
});
}
});
いいねカウント数の表示やボタンクリックした時の処理は onAuthStateChanged
でユーザー認証した後に書いたらいい(っぽい)。
querySelectorAll('.CountLike')
でNodelistを取り出して [].forEach.call
で関数走らせてる(っぽい)。
読み取りと書き込み
データベースから参照 ref(getDatabase())
したデータを持ってくるときは snapshot.val()
とか使えばいいらしい。
innerHTMLで取得した値を入れる。
参考:ウェブでのデータの読み取りと書き込み | Firebase Realtime Database
runTransaction
で値をupdateしている。
多分ここはもっといい方法がある……(というかちゃんと理解していないでいる)。
セキュリティルール
{
"rules": {
".read": "null !== auth.uid",
".write": "null !== auth.uid",
"$iine" : {
"likes": { ".validate": "newData.isNumber() && newData.val() >= 0" },
"$other": { ".validate": false }
}
}
}
- (匿名)認証していないユーザーにはreadもwriteの権限も与えない
- 変数
$iine
の下のlikes
はデータを検証(ゼロ以上の数値のみが許可される) - 変数
$other
を使って、既にあるlikes
以外の値の書き込みを許可しない
もっとより良くすることはできると思いますが、現状はここまで。
いいねボタンいろいろ
2022/10/23時点で見つけたもの
サーバー設置型
- 個人サイト向けいいねボタン・改 (Javascript(jQuery) + PHP)
- Ajaxいいねボタン (Javascript(jQuery) + PHP + MySQL)
サービス型
- Lyket - Instantly add like buttons to any website!
- React, Wordpressプラグイン, HTML, API 等で利用できる
- Reaction Buttons byShareThis: モバイル、高速絵文字ボタン
- 絵文字のリアクションボタンをページに追加できる
その他
- Applause Button (CDN etc)
探してみればいろいろあるんだなと思いました。
実際に利用してはいないんですが……シンプルそうなLyketはNotionにも使えるようでちょっと興味があります。 あと、APIサーバーを立てて実装するApplause Buttonみたいなことは自分でもやってみたくなりました。