Mimicking a Holographic Effect for Mercard

こんにちは!Merpay iOSチームのKrisとMikael、そしてMerpay Androidチームのanzai(@off2white)とshinmiy(@shinmiy)です。

本記事は、2022年12月8日に公開された「Merpay Advent Calendar 2022 」8日目 メルカードの舞台裏編 を翻訳し、加筆修正しています。

メルカードのホログラムロゴを再現する

メルカードは「メルカリ」の利用実績等を元に利用限度額や還元率が決まり、申込みから利用時の即時通知、履歴確認、柔軟な清算管理まで「メルカリ」アプリで完結するクレジットカードです。スマートフォンと一体化することで、より安全性と利便性を追求した支出管理を実現しています。「メルカリ」アプリからカードにアクセスできるため、カードと同じホログラムロゴをアプリ内で表現し、手持ちの物理カードとバーチャル上のカードUIの共通性をもたせることでお客さまの体験の統一をはかりたいと考えました。従来のPNGやLottieのアニメーションでは表現しきれないため、ジャイロセンサーを利用してデバイスの向きとロゴの色を対応させ、物理カードを手に持っているときのホログラムロゴの反射を模倣することにしました。この記事では、メルカードのロゴを再現するまでの舞台裏をご紹介します。

ジャイロセンサによるホログラムの再現

アプリ内でホログラムを再現するために、まずジャイロセンサーでデバイスの向きに関するデータを収集し、HSBのカラーホイールのグラデーションにマッピングしています。このグラデーションをロゴでマスクすることによって、あたかもロゴが色を反射しているかのように見えるのです。

ジャイロスコープ

ジャイロセンサーは、3つの空間軸に対するデバイスの位置をリアルタイムに測定することができます。ユーザーが端末を回転させると、その回転が3D空間上でどのように見えるかを計測します。その値をもとにグラデーションカラーを作成します。

色相

グラデーションの表現では、デバイスの位置からアイコンの色を判断する必要がありました。今回は、HSBのカラーホイールを使用することにしました。3軸の角度を0度から360度までの値に変換し、グラデーションの変化に対応させました。

Created hologram logo by motion data flow [1]

[1]: Apple Developer : Getting Raw Gyroscope Events (https://developer.apple.com/documentation/coremotion/getting_raw_gyroscope_events)

実現までの道のり

もともとはデザイナー発の案としてはあったものの、ホログラムロゴは他のタスクに優先されてなかなか着手ができない状態でした。(クレジットカードの立ち上げにはやるべきことがたくさん!)しかし、Asami KubotaさんとWenxi CaiさんがインターンとしてiOSチームとAndroidチームに加わったことで、実現に向けて動き出すことができました。開発期間が短く、他と独立した機能はインターンで扱うプロジェクトとしてぴったりでした。

端末のセンサーを使って端末の傾きに連動してアイコンの色を操作する手法についてPoCを見ながら開発チーム内で議論しました。問題なく実現できそうということがわかり、そこからはデザイナー、エンジニア、PMが一体となって機能の実装に取り組むことになりました。

初期PoCの画面

物理カードのロゴを再現しつつ他のUI要素になじみ、自然な見た目になるように、何パターンもUIを試作しながら開発を進めました。実際に端末に入れていろいろな角度から見て試していたので、他のチームから腕をひねったり下から見たりと何をやってるんだろう?と不思議な目で見られていたかもしれません…

配色やセンサーの感度、色相や彩度の制限など、複数の変数を考慮しながら調整を進めました。各変数が全体の仕上がりにどのように影響するかをデザイナーが確認できるように、スライダーを追加したビルドなども用意しました。

各種パラメータを確認するためのスライダー

最終的に満足できるバランスが見つかったので、PoCの実装を本番アプリに移植しました。

エネルギー効率

アプリに視覚効果を実装する際に気になるのは、端末が熱を持ったり、通常より早くバッテリーを消費したりといった問題です。

そのような問題を避けるため、以下の対応に取り組みました。

モーションモニター設定

前述したように、この新機能はiOSのモーションモニター機能を利用しています。これにより、端末の位置をリアルタイムに計測・収集することができるのですが、短い周期で表示の更新を行うと電力を多く消費してしまいます。

消費電力とアニメーションの滑らかさのバランスを取るために、さまざまな設定を試し、最終的にはデータ収集の頻度を60回/秒に設定しました。また、データ収集に関連する問題が発生しないように、Appleの推奨するMotion Managerの ユニークなインスタンスを作成することに気をつけました。

低電力モード

iOSでは、ユーザーがバッテリーを節約しようとしているかどうかを知るために、デバイスの電源モードを監視することが可能です。

低電力モードの設定

お使いのデバイスが自動的に低電力モードに切り替わるとき、またはバッテリーを節約するために手動でこのモードに切り替えるとき、アプリが電力を消費する機能を使用しないようにする必要があります。そのため、低電力モードがオンのときは、ホログラム効果を無効にして、代わりに静的なアイコンに置き換えています。

必要なときだけホログラムを動かす

「メルカリ」アプリは多くの画面や機能を含んでいます。アプリのメイン機能の1つであるメルペイは、現在アプリ内で唯一ホログラム効果が使われている部分となり、より具体的には支払いタブでのみ使用されています。しかし端末の傾きの監視は、他の画面やバックグラウンドでも意図せず発生する可能性があります。

お客さまが実際に見ているときだけホログラムを動かしたいので、効果をオン/オフするためにSwiftUI のライフサイクルを使用します。

次のような場合に起動します。

  • 支払いタブがアクティブで表示されている場合

以下の場合は、無効化します。

  • お客さまが決済画面を表示していない場合
  • お客さまが決済画面にいて、例えば支払い設定などのサブ画面に遷移している場合

このホログラムを無効にするときは、モーションモニターのリフレッシュレートを下げるだけでなく、完全に停止させるようにしています。この効果はUI画面のマスクやグラデーションを含むため、UIも静的なアイコンに置き換えています(低電力モード時と同様)。

iOSの実装で工夫した点

実装について

iOSでは、UIは古いUIKitではなく、Appleの最新のUIフレームワークであるSwiftUIを使って実装しました。そのためCombineとSwiftUIのPublishedプロパティを利用して、新しいモーションデータをリアルタイムで受信したときに、ロゴのグラデーションの色、角度、彩度を手動で操作することなく自動的に更新することができたのです。

メルカードのロゴのUIでは、ロゴの画像をグラデーションの上に置くためのマスクとして使用し、ロゴ自体がホログラムであるかのような効果を与えました。SwiftUIはビューをスタックしてレイヤー化する簡単かつ効果的な方法を提供するので、実際のビュー関連のコードは非常に少なく、簡単に作成することができました。UIKitで同様の効果を作るには、ビューの制約やサブビューの追加に関連する多くのコードが必要で、グラデーションの属性を更新するには、より手作業で面倒なプロセスが必要でした。

ライフサイクル

不必要なバッテリー消費を減らすためにエネルギー使用量を監視することが重要だったので、メルペイの支払いタブを監視して、表示されていないときにホログラムが無効になっていることを確認しました。この一連の処理の間、SwiftUIのライフサイクルイベント onAppear はiOS 14で奇妙な動作をしており、予期しないタイミングで複数のtrueとfalseの値を与えていました。そのままにしておくと、場合によってはホログラム効果がバックグラウンドで実行されたままになるので、この問題を修正する方法を見つけ出す必要がありました。その結果、UIKit のビューコントローラーのライフサイクルを監視することにしました。これにより、より正確な測定が可能になり、予期しないときにホログラムが動いてしまうことがなくなりました。

Androidの実装で工夫した点

AndroidのUIは、iOSと似てJetpack Composeを使って実装されています。これにより比較的簡潔にUIコンポーネントを他の実装から切り離し区分けすることができました。ただし、端末のセンサーを使用しているのでAndroidのライフサイクルを回避することはできません。センサーからの値を受け取り、表示する色を算出するプロバイダーと、算出した色を受け取って画面にアイコンを実際に表示するUIコンポーネントに分けて実装しています。

状態からロゴを描くのはとてもシンプルでした。Composeのおかげで、50行程度のComposableで実現できました。もしこれを旧来のViewシステムでやっていたとしたら、ボイラープレートでもっと長くなっていたことでしょう。他にもフィーチャーフラグを使いやすいところもメリットでした。単純なif文だけで実装を完全に分割することができています。

途中、エミュレーターを使って調査をしているときに、エミュレーターの回転表示と実際の値が一致せず、戸惑ったことがありました。これは、表示上はデバイスの中心でモデルを回転させる制御をしている一方で、取得できる値は実際にセンサーのあるカメラの位置を中心とした値であるためでした。

エミュレータでの端末の回転

ホログラムのQA

メルカリのような巨大なプロジェクトでは、お客さまが使うアプリで意図しない挙動が発生しないようにするためのQAが非常に重要です。

担当するQAチームは、多くの端末でテストシナリオを実行しています。

今回の機能は、特にUIのレイアウトや端末の消費電力に関係するので、さまざまな種類の端末を集めて詳細なテストを行う必要がありました。

Android、iOSともに、次のような端末で検証が行われています。

  • 古い端末:古い端末は、新しい端末よりも性能が低いことがよくあります。古いチップセットを搭載していて、今回の機能で端末が熱くなるなどの可能性があります。
  • 新しい端末:追加する機能で端末が熱を持たずに、またフレームレートの低下を伴わずに動く必要があります。そうでなければそもそも実装する意味がありません。新しい端末の中には、たとえばiPhone 14 ProのDynamic Islandのような新しいUI機能もあります。お客さまがどんな端末でアプリを使っても素晴らしい体験ができることは重要ですし、それはメーカーの新しいフラッグシップ端末を使用する際にも同じことがいえます。
  • 画面の大きな端末と小さな端末:大画面でUIに問題がないことを確認するために、タブレット端末でもテストします。小さい画面でもUIが正しく動作することを確認するため、iPhoneSEのような端末も使用します。

テスト中に何らかの問題が発生した場合、バグチケットが作成されます。その後エンジニアがバグを修正し、QAチームがテストを再開します。

最後に

最初のコンセプトから完成まで長い道のりでしたが、チームとして集まってホログラムロゴを完成させ、無事お客さまに届けることができました!「メルカリ」アプリのほかの機能と同じように様々な工夫をしながら開発したので、皆さんもぜひお試しください。

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加