
オリジナルのスタンプを作って遊ぼう! REALITY Advent Calendar 2023
こんにちは、サーバエンジニアの abe です。この記事は REALITY Advent Calendar 2023 の6日目となります。今年の開発合宿ではスタンプで遊ぶことをテーマに開発を行ったので、その成果を紹介します!
アバタースタンプ
皆さん、アバタースタンプ使ってますか?
REALITY にはチャットで自分のアバターが映ったスタンプを送ることができるアバタースタンプ機能があり、チャットでのコミュニケーションに大活躍してくれています。アバタースタンプ可愛い! 最高!
しかしたくさんの種類のスタンプがあっても、意外と使いたい状況にマッチしたスタンプが見つからなかったりするんですよね。
例えばエンジニアなら「LGTM」スタンプを使いたいことがあると思いますが、今のところ「LGTM」スタンプはなかったりとか。そういうスタンプがあればもっとコミュニケーションがはかどるのにな〜。
今回お届けするのはそんな時のためのソリューション。オリジナルのスタンプを簡単に作れる機能を作りました!
※この記事で紹介する機能は開発合宿で作ったプロトタイプであり、今後リリース予定があるものではありません。
スタンプクリエイター
こちらが今回作ったスタンプクリエイター機能です。どん!

こちらはベースの画像の上にお絵描きしたりテキストを入力したりすることでオリジナルのスタンプを作ることができるツールとなっています。
「ベーススタンプ選択」の欄に既存のスタンプの画像が並んでいるので、この中から好きな画像を選んでクリックすると上のキャンバスにそのスタンプが表示されます。ベーススタンプは上の画像だと9種類しか出ていませんが、この下にずらっと全種類並んでいるのでけっこう壮観です。
スタンプを選んだらお絵描きをします。お絵描きと言いつつ矩形・楕円・テキストの追加と選択レイヤーの削除くらいしか実装していませんが、任意の文字入力ができるので割といろんなスタンプを作ることができます。

今回は先ほど例に挙げた「LGTM」スタンプを作ってみました。
あとは「アップロード」ボタンを押すと……なんとこれだけで今作ったスタンプがチャットで送れるようになっています!

もちろんこれはアバタースタンプなので、誰でも自分のアバターでこのスタンプを使うことができます。
コーデを変えてスタンプを再生成すればそのコーデが反映されたスタンプになりますし、一度送信したスタンプはコーデを変更しても送ったときのまま。他のアバタースタンプと一緒です。

この機能があれば誰でも簡単に送りたいスタンプが作れるので、より楽しくコミュニケーションできますね!
やってること
合宿の短い時間で素早く作るため、メインとなるツールは web に実装しました。実装には Fabric.js を使用し、HTML5 の canvas 上でお絵描きできるようになっています。アップロードボタンを押すと、canvas のデータを png 画像に変換して Cloud Storage にアップロードします。
// canvas: fabric.Canvas
const dataUrl = canvas.toDataURL({
format: 'png',
width: 512,
height: 512,
})
const buffer = Buffer.from(dataUrl.split(',')[1], 'base64')
const file = new File([buffer], 'filename', { type: 'image/png' })
const formData = new FormData()
formData.append('file', file)
await axios({ data: formData, ... }) // アップロード
バックエンド側はソロ、コラボに続く新しい種類のスタンプとして実装しています。サーバ内ではアバタースタンプを interface として扱っており、interface を満たす型とそれを生成する factory を実装すれば主要な機能は割と動いたので、合宿の短い時間でも何とかなりました。コラボスタンプ対応のとき今後に備えて interface にしておいたのが役に立って嬉しい。
クライアント側については、今回は合宿ということでサーバエンジニアの自分1人で開発を行ったため特に手を加えていません。
クライアント開発なしでどうやってこの新しいスタンプを動かしているのかというと、クライアントにはこのスタンプを「コラボスタンプ」扱いで返すことで実現しています。
コラボスタンプの仕組みについては以前ホンダさんが解説してくれたこちらの記事が詳しいので詳しくはそちらを見ていただきつつ、画像を拝借すると、

このように自分・コラボ相手の2種類のポーズで撮影した画像をアップロードし、共通の背景・前景と重ね合わせることでコラボスタンプにしています。コラボスタンプとして1つのスタンプに見えているものは、最大4枚の画像を重ね合わせたものなんですね。
つまり「複数の画像を重ね合わせて1つのスタンプとして表示する」機能がクライアントには備わっているので、スタンプクリエイターでは

このような「前景」相当の画像のみを作成してアップロードし、各自のベーススタンプ画像と合わせてサーバから返すことで、誰でも自分のアバターで使えるオリジナルスタンプを実現しています。
まとめと感想
今回はオリジナルのスタンプを作って遊べる機能を作りました。スタンプのアーキテクチャを活用した機能を作れて楽しかったです。発表スライドの全ページにスタンプ画像を入れたり、デモでは直前に発表していたチームのネタをスタンプに取り込んだりとスタンプで遊び倒しました。
スタンプクリエイターはあくまで開発合宿のネタなのでリリース予定があるわけではないのですが、アバタースタンプは可愛いし楽しいのでもっと色々やっていきたいですね!
明日はうすぎぬ&メタルおじさんのチームによる「性格診断を使ったユーザレコメンド機能を作ってみた」です。お楽しみに!