Reflective UI実践:現実世界が映り込むUI表現
Reflective UIと呼ばれる表現がにわかに注目されています。そのいくつかの事例紹介や、私自身が実際に実装してみてどうだったかの所感を書き留めておこうと思います。
Reflective UIとは
Reflective UIとは、光や映像の反射表現を活用してUIの質感を高めた表現を指します。ジャイロや加速度センサーを使って擬似的に反射を表現したり、カメラで取り込んだ映像をUIのテクスチャとして活用して、より現実感を持たせた表現などがあります。
カメラを使う場合、例えばフロントカメラでユーザーの顔や背後の映像を撮影しリアルタイムに加工して、テクスチャとしてUIの見た目に反映します。これがスマートフォンで実装されるとまるでGUIが鏡のように映り込む質感を持った物体かのように錯覚するので、「クールな新しい表現」として注目されています。
Reflective UIに明確な分類や定義があるかは定かではないのですが、英語圏のデベロッパーコミュニティを眺めていると、SwiftUIやWeb系の技術でさまざまな表現を模索する動きが見られます。
Reflective UIの特徴と例
私なりの解釈ではありますが、ざっと特徴を挙げてみます。
いくつかの実装例を挙げてみます。
Aqua button by Morten Just
懐かしいMac OS X Aqua風のボタンに、カメラ映像を反射させる表現を施すアイディアです。SwiftUIで実装されています。ツイートにぶら下がるスレッドに設計に関する詳しい説明があります。
Shiny button by Alex Widua
Reflective UIが注目されるきっかけになったアイディアの一つです。このメタルボタンは撮影者や背後の視界がそのまま映り込んでいるように見えるので、まるで本物かのように錯覚します。テクスチャの加工具合も絶妙でリアルさを引き立たせているように思います。
私もこのツイートに触発されて、iPhoneで同様のメタルボタンを実装してみました。(この後で詳しく紹介します)
Reflective CD by Shane Levine
ケースに収まったCDがGUIで再現されています。CDの表面にはフロントカメラで取り込んだ映像を使って反射を演出しています。それに重ねるようにしてCD特有の虹に見える構造色もオーバーレイし、リアルさを演出しています。
Reflective UI by Jordan Singer
これはGUIでメタルや鏡を模すのではなく、バックカメラの映像を磨りガラスのテクスチャに反映するアイディアです。iPhoneの裏側の視界がiPhoneの中に映り込むので、「ガラス風に見える何か」がよりリアルに見えるようになります。まるでiPhone自体にガラスがはまっているかのようにも錯覚します。
Shiny card in SwiftUI by Meng To
この界隈では有名なMeng To氏も反射するキラ系カードのSwiftUI実装をツイートしていました。タップするとより白く光って見えるところも、指の衝撃でカード表面の反射の具合が変化したような演出になっていて、面白いですね。
Holo effect by Orlando Gabriel Herrera
キラカード (holo) をソフトウェアで再現するアイディアです。この辺りの実装ではカメラは必要なく、ジャイロや加速度センサーを使って実装できるので、ちょっとした遊び心として、しかも実用性を損なわずにUIに付与することが容易にできそうです。
似たような例としてポケモンカードのキラカード風の効果を描画するためのコードも見かけたのですが、著作権的にだめそうだったので直接の紹介は控えます。
LokkingGlassUI
シマー効果(光が動いて見える表現)を適用できるSwiftUI製の実装です。カードの映り込み演出やテキストの強調演出などで実用的かもしれません。
Metal Effect using the Accelerometer by Philip Davis
SwiftUI界隈で有名なPhilip Davis氏の作品の一つです。加速度センサーを利用して金属の反射表現をリアルに演出しています。
このような表現は最近出てきたものではなく、iOS 6の頃のMusic appが備えていた音量スライダーにも見られました。覚えておられる方もいらっしゃるのではないでしょうか。
Digital Pass by Max
Reflective UIの亜種のようなアイディアですが、3DモデリングツールのSplineを使って、ビニール製のパスケースを模した作品が公開されていました。表面の質感がそれっぽいです。
(追記:当初Philips Hue Syncの例をここで紹介していましたが、Reflective UIの説明としては少し解釈が飛躍し過ぎていると考え、削除いたしました。)
Reflective UI実践:メタルボタン(iOS)
Alex Widua氏のアイディアを見かけたとき、私も自分で作ってみたくなったので、作ってみました。最近はこういった実装にはSwiftUIが盛んな印象ではありますが、自身で使い慣れたUIKitをベースとしてiOS appを実装しました。
まず完成したのは以下のようなものです。触発されたアイディアと同じようにメタルボタンとして作りましたが、元のアイディアはWeb実装だったので、私はiOSネイティブで再現しました。
全体のコードは公開できる準備ができていないためデザインの要点のみ紹介します。
仕組みとしてはそう複雑ではなく、フロントカメラの映像を映すレイヤーをボタンのビューに重ねて、適当なフィルタで加工して角丸にクリップする、というアプローチです。
制約
まず制約があります。
こういった制約があるので、現実的には実用性はそう高くなく、まだ実験室レベルのアイディアにとどまってしまう気がしています。より斬新なアイディアが登場するか、プラットフォーム側で何かサポートしてくれるような機能が追加されれば、有用な表現として期待できると思います。
金属反射をリアルに見せるフィルタ効果
私の実装では、カメラの映像に対してリアルタイムに画像フィルタを適用して金属質感を高めています。映像ストリームに直接Metalシェーダーを適用するようなこともおそらくできますが、今回はそのような高度な技術を使わずにサクッとやりたかったので、iOSが用意しているより安価な画像処理の仕組みを活用しました。
カメラの映像を描画する方法としては、AV FoundationのAVCaptureVideoPreviewLayerを使いました。これはCALayerのサブクラスなので、Core AnimationのコンテキストやUIViewの中で扱いやすいものです。適当にレイヤーを重ねて、影やクリッピングをするためのレイヤーを作ります。その過程で「フィルタリング用レイヤー」というものを前面に重ね、これに compositingFilter を適用します。
compositingFilter
compositingFilterとは、CALayerにPorter-Duffブレンドを適用するためのプロパティです。オーバーレイとか覆い焼き(Dodge)とかのやつですね。AppleのドキュメントによるとこのプロパティはiOSではサポートされないと書かれているのですが、適切な文字列でブレンド名を指定するとなんと機能するブレンドモードが存在します。これは裏技的に知られています。
今回私は2種類のブレンドモードを利用しました。
それぞれ何の役割なのか簡単に説明します。
まずsaturationBlendModeの方は、映り込ませる(ように見せる)カメラ映像全体の彩度を下げるために使います。彩度が高いままだと金属っぽくなくなることがわかったので、見た目の調整として敢えて彩度を落としました。完全に落としてしまうとモノクロになってしまうので、少しだけ色味は残しておきましょう。
colorBurnBlendModeの方は、文字通りColor Burn / 焼き込み(カラー)を適用するためのブレンドモードです。金属質感(イメージで言う下部の黒っぽいモヤ部分周辺)を作るために使うのですが、単にブレンドモードを指定するだけだとこうはならないので、ブレンドする素材の方にもひと工夫を加えます。
ガウシアンブラー的な効果を得る
テクスチャとして使うAVCaptureVideoPreviewLayerは、そのまま描画するとカメラの映像がパッキリ映り込むので、金属として認知するなら表面の反射率が非常に高く見えるか、あるいはボタンテキストを判別しにくくなります。今回はSNS映えするよう顔の映り込みを避けたかったこともあり、テクスチャをある程度かぼかす処理を加えることにしました。
カメラから取り込まれる映像にリアルタイムにブラーフィルタをかけることになるので、パフォーマンス含め少し技術検証が必要なポイントです。
iOSでブラー効果を得る方法はいくつか考えられるのですが、一番手っ取り早いのはSwiftUIで.blur()をつけてやる方法です。ですが今回は主に私の都合でSwiftUIを採用しなかったので、別の手立てが必要でした。(カメラの映像に適用可能なのかは試せていません。)
こうなると少々厄介です。古くからiOSプラットフォームではリアルタイムレンダリングできる、かつ描画パフォーマンスの高いブラー効果は実現が難しく、iOS 16の時代でも実現可能性に幾らかの問題があります。
まず考えたのはUIVisualEffectViewを使ってぼかす方法なのですが、これはうまくいきませんでした。何となくうまくいきそうな気がするのですが、残念なことにAVCaptureVideoPreviewLayerに対して適切にブラーがかからないのです。これでは今回のユースケースには使えません。
CALayerにCore Image Filterを適用できるbackgroundFiltersプロパティも検討したのですが、これはiOSではまったく機能しません。ドキュメントにもそう書いてありますし、compositingFilterのような裏技もどうやら存在しません。Macだったらこれで好き放題だったんですけどね。
いろいろ調査した結果たどり着いたのは、UIVisualEffectViewのプライベートAPIに触れてブラー効果を得るという方法です。具体的なコードは以下のStack Overflowにあるので参考にしてみてください。パラメータでボケ具合も好きに操作でき、リアルタイムに処理できます。“_UICustomBlurEffect”をキーワードにググると他にも情報が得られるので、興味があれば調べてみてください。
今回はApp Storeに載せるものでもなかったためプライベートAPIの手段を取れたのですが、製品として設計するならば大きな懸念点になったことでしょう。
線形グラデーションでブレンドの度合いに傾斜をつける
ブレンドする素材の方のレイヤーは、CAGradientLayerのaxialモードで線形グラデーションを描画します。パラメータは適当にいじってみても良いのですが、私が最終的に選んだのは以下のような具合です。
要は上から下に向かって、白から黒、0%から40%透過でリニアに変化するグラデーションを作りました。これをColor Burnでブレンドすると、上方の白っぽい部分は透過し、ある地点から下方までの黒っぽい部分はColor Burnが適用(暗くブレンド)されます。アルファ値で傾斜をかけているので、境界がじんわりした感じに見えるようになります。
これも狙ったというよりかは、半分は試行錯誤しててたまたま見つけた「効果」だったので、この辺はいろいろパラメータで遊んでみると他にも面白い見え方を発見できると思います。
そのほかの工夫では、ボタンのフレームを作るためのレイヤーも重ねることで、結果的にはより金属感が増す効果が得られました。テキストにもiOS 6の頃に流行ったようなエンボス風の影を少し入れて凹凸感を出してみました。
おわりに
以上がReflective UIというものの紹介です。カメラを使う場合は特にAppleデバイスでの制約が大きいため、なかなか実用には向きづらいというのが今の所の評価ではありますが、私としてはGUI表現の新たな可能性に気付かされるきっかけを得ることができました。
リアルタイム画像処理はiOSではAPI制約で使えない機能が多いのですが、プラットフォームを変えるとそういった制約がない場合もありますので、このアイディアを応用して色々な表現に挑戦してみるのも楽しいと思います。