こんにちは!メディア統括本部デザイナーの内田です。
サイバーエージェントのメディア管轄では、モックを作る時にProtoPieをよく使っています。この記事では私が業務+αで習得したProtoPieの使い方について、基本からちょっと込み入ったところまでお伝えしたいと思います。
記事がかなり長くなってしまいましたが、最終的にこんな動きが出来上がります。
このサンプルはこちらから実際に触れます。またダウンロードして中身を見たりできるのでぜひご覧下さい。(なお出てくる可愛いわんちゃんは弊社エンジニア谷のマメヒコとクロスケです。尊い・・・。)
ちなみにこの記事で使用したProtoPieのバージョンは4.0.3、MacOS 10.14.6です。ProtoPieはこちらから1ヶ月無料でダウンロードできます。
目次
1. なぜモックが必要なのか
なぜProtoPie?
2. どうやってProtoPieを活用してプロダクトを開発しているのか
3. ProtoPieを使ってみる
超基本編 – ボタンをタップしたら遷移
基本編 – 滑らかな遷移アニメーション
中級編 – スクロールに連動した動き
上級編 – 数式と変数を使ってみる
番外編 – ゲームを作る
4. おわりに
1. なぜモックが必要なのか
新規開発の現場でモックが果たす役割は、フェーズによっても異なります。
最初はビジネスサイドで作ろうとしてるアプリの、全体感の把握のために必要になります。まだ要件が決まりきっていない段階から、欲しい体験をモックとして素早く具現化し、それを見ながらさらなる要件を決めていきます。
ある程度できてきたら、そのモックでユーザーテストを行い、使いにくい部分を確認していきます。そして実装の段階では、細かいインタラクションをエンジニアに伝えるためにもモックが必要になってきます。
なぜProtoPie?
サイバーエージェントの開発現場では、アプリのクオリティの担保と、競合アプリとの差別化のために、UI、インタラクションに特に力を入れています。そのこだわりを作り込み、チームメンバーに伝えるためにも、どんなツールを使うのかも重要です。
そのため、簡単な遷移しか作れないプロトタイピングツールより、インタラクションを自由に作り込めるツールが必然的に開発現場で導入されるようになってきます。
また細かい作り込みが出来ることと同じくらい、簡単に素早く作れることも重要になります。フィードバックを素早く反映したり、複数のパターンを作って比較する必要があるためです。
こうした理由から直感的な操作で作業でき、思い描いたことは大体実現できるProtoPieが徐々に社内で広まっていきました。
2. どうやってProtoPieを活用してプロダクトを開発してるのか
今担当しているプロジェクトでも、ProtoPieは開発の軸と言っても過言ではないほど活躍しています。今回はビジネスサイドとのすり合わせの時点で、社外パートナーの方にもモックを触ってもらう必要がありました。その時に彼らに「イケてる!」と思ってもらえるように、イージングや遷移のタイミングまで拘り、ほぼ全ての画面でタップできないボタンが無いよう詳細に作り込みました。
そしてそのリアルなモックを使い、社内でユーザーテストをして、新たに出た使いづらそうな部分を直して少しずつブラッシュアップしていきました。
開発が始まる段階でも、モックは工数の見積もりの役に立ちました。また実装にあたっても、アニメーションのタイミングやイージングなどを伝え、細かいところまで再現してもらっています。また、エンジニア側からローディングの時間やエラーパターンなどについての指摘ももらい、さらにブラッシュアップしていきました。
と、長々と仕事っぷりを説明させて頂きましたが、私がProtoPieを使い倒した中で得た、基本の使い方から上級編まで、紹介していきます!
3. ProtoPieを使ってみる
超基本編 – ボタンをタップしたら遷移
まずは「ボタンをタップしたらページを遷移する」という動きを作ってみましょう。
シーンにオブジェクトを配置
まず遷移前と遷移後のページを作ります。Sketch、Figma、AdobeXDならファイルごとインポートできます。
Sketchファイルはこちら。
https://github.com/ukn530/how-to-use-protopie/raw/master/DevelopersBlog.sketch
ProtoPieではアートボードはひとつずつシーンとしてページが分かれます。2つシーンを作りましょう。ウィンドウ左のこのアイコンからシーンを作れます。さらにシーン名をダブルクリックして、それぞれHome、Detailと名前をつけておきます。また中央上からデバイスもiPhone Xにします。
Sketchを開いておき、左上のインポートからSketchを選択しましょう。該当のアートボードを@3xで読み込みます。
この時、影と角丸もアニメーションできるのでProtoPie側でつけましょう。Sketchと同じように右側のインスペクタから設定できます。コンテナー(レイヤーをまとめるグループみたいなもの)に角丸をつけたら、一番下の「サブレイヤーをクリッピングする」にチェックをつけてマスクさせましょう。
さらにスクロールもここで設定します。上部メニューのコンテナーからScrollコンテナーを作成。スクロール領域の大きさを設定(今回はスクリーン全体)し、その中にスクロールしたいレイヤーを入れます。
ここまでできるとこんな感じです。
インタラクションをつける
ProtoPieでインタラクションをつける時に必要なのは以下2つです。
- トリガー タップ、ドラッグなどの操作(入力)のこと
- レスポンス オブジェクト移動、ページ遷移などの画面の動きのこと
今回の「タップしたらページ遷移」はトリガーにタップ、レスポンスにページ遷移を割り当てます。
トリガーに設定したいレイヤーを選択、アートボード右側の「トリガーを追加」をクリックし、Tapを選択します。
レスポンスはTapの下の「+」をクリックしJumpを選択、右のインスペクターで飛びたいシーン(Detail)を設定します。
飛んだ先のクローズボタンにも同じ設定すると、以下のような超シンプルな遷移ができます。
基本編 – 滑らかな遷移アニメーション
「これくらいならSketch単体でもできるよ!」という感じなので、リッチにしていきます。ここでも基本のトリガー&レスポンスは変わりません。
タッチ中画像を小さくする
Tapトリガーと同じように、TouchDownとTouchUpのトリガーを追加し、両方レスポンスにScaleを設定します。Scaleはサイズじゃなくファクターの項目でパーセンテージを指定してみましょう。TouchDownで95%、TouchUpで100%にしてみました。また拡大縮小にかかる時間を0.3にしました。
この状態でプレビューすると左上に向かって小さくなってしまうので、対象レイヤー(Content1)を選択し、右のインスペクタから基準点をX: 50 Y: 50にします。これで中心に向かって拡大縮小するようになります。
遷移先に画像を繋げる
実際にシーン間で画像を共有することはできませんが、それっぽく見せることはできます。遷移が発生するときに遷移先の画像の位置まで画像を移動させます。
やることが多いので羅列します。
– シーンHome –
- さっき設定したJumpのスタートディレー: 0.3(タップ0.3秒後に遷移)
- TapトリガーにContent1のScaleを追加。サイズを幅: 375 高さ: 281(遷移後のサイズにする)
- コンテナー内の画像も拡大させたいので、中の画像のリサイズ制約でマージンを上左右固定(幅固定を外す)、タイトル類は下左右マージン固定。
- TapトリガーにContent1のMoveを追加。基準点をさっき中央にしたので、Content1幅と高さの半分の値に移動させるとスクリーン上部にぴったり移動できる。X: 375/2 Y: 281/2と入れると便利。
- タイトル類が邪魔なのでContent1内のTitleレイヤーを選択し、Tapトリガー内にOpacityを追加。不透明度を0に。
- 「今日のニュース」などのレイヤーの上にContent1を移動させたいのでTapトリガーにReorderを追加。Content1を最前面(なぜかが最前面アイコン)に移動させる。
- 上記で追加したScale、Move、Opacityの時間: 0.3 に。
- TapトリガーにContent2のOpacityを追加。不透明度0に。
- TapトリガーにContent3のOpacityを追加。不透明度0に。
さらに滑らかに見せるために遷移先シーン側も工夫しましょう。
– シーンDetail –
- トリガー追加でStartを追加(Startはこのシーンに移動した瞬間に実行されるトリガー)
- StartトリガーにContentのOpacityを追加。不透明度: 0 時間: 0に(ページが開く瞬間にContentを消す)
- StartトリガーにContentのOpacityを追加。不透明度: 100 Easing: Ease Out 時間: 0.3に(上で設定したOpacityを戻してContentが出現するアニメーションを作る)
- StartトリガーにContentのMoveを追加。指定値ずつ移動でY: 50 時間: 0(このページが開いた瞬間に下に50ずらす)
- StartトリガーにContentのMoveを追加。指定値ずつ移動でY: -50 Easing: Ease Out 時間: 0.3(上で設定したずらしを0.3秒かけて戻す)
- StartトリガーにButtonCloseのScaleを追加。ファクターを X:0 Y:0 時間: 0。(ButtonCloseレイヤーの基準点はx:50 y:50)
- StartトリガーにButtonCloseのScaleを追加。ファクターを X:100 Y:100 Easing: Spring Friction: 20 スタートディレイ: 0.3。
ここでプレビューしてHomeとDetailを行ったり来たりしてみると、HomeでContent1が拡大されたままになっているのが分かります。これは以下の方法で直せます。あとDetailからHomeに帰るときの動きを入れておきましょう。
- シーンHome、DetailそれぞれのJumpレスポンスの中の、「選択したシーンをリセット」にチェック
- シーンDetailのJumpレスポンスのエフェクトをSlide Out 上から下 に。
- シーンDetailのStartトリガーの設定で「Jumpと同時にスタート」を追加。
ここまで設定すると以下のようになります。
Easingや時間はお好みで変えてみてください。最初に設定した角丸やシャドウも、ここでいじるとより丁寧になります。
中級編 – スクロールに連動した動き
例えばTwitterのプロフィール画面のように、スクロール量に応じて画像を大きくしたり、タブバーがヘッダーにぶつかったらスクロールしないようにしたい時があります。
そんな時はChainトリガーを使います。今回はDetailのスクロールでパララックスとTwitter風のヘッダー画像拡大を入れてみましょう。
- スクロールを設定してあるレイヤー(コンテナー1)を選択し、Chainトリガーを追加。右のインスペクタでレイヤー名の下にあるプルダウンで「スクロール」を選択。
- ChainにHeaderのMoveを追加。Rangeの値を下記のようにして400スクロールする時にHeaderのY座標が-50するようにする。Xには何も入れなくてOK。
- ChainにHeaderのScaleを追加。Rangeの値を下記のようにして-400スクロールする時にHeaderの高さを+400に拡大するようにする。幅は画像の縦横比を保つように実寸を設定。
- ここでプレビューしても拡大されないのは外側のコンテナーのみ拡大され、中の画像が拡大されてないから。中の画像のリサイズ制約でマージンを固定。
- 左上を基準に拡大されてしまうので、Headerの基準点をX:50 Y:0(中央上)に設定。
- Chainにブラー画像のOpacity追加。スクロール: 0でOpacity: 0、スクロール: -20でOpacity: 100くらいに設定。(画像が非表示になっている可能性があるのでレイヤーパネルで目のアイコンをクリックして表示させてください。)
これでスクロールの動きに連動して、画像が変化するようになりました。
上級編 – 数式と変数を使ってみる
さて、ここまでくると他のコンテンツを押した時も遷移させたくなるのが人の性です。インタラクション類はコピペできるので、2つほど複製してContent2、Content3で同じ設定をします。
そこで2つのことに気づきます。
- スクロールしてからタップすると移動する画像がずれる
- タップしたコンテンツによって遷移先の画像を出し分けたい
これらはそれぞれ数式と変数を使うと実現できます。
スクロール位置を取得する
基本編でつけたタップ時の画像の移動は、どうやらスクロールした分ずれるようなのでMoveのYの値に、スクロール量を足してあげる必要があります。
すでに入力してあるY座標の140.5をクリックし、入力欄右側のfxを押します。
すると入力欄が大きくなるので
140.5 + `コンテナー 1`.scrollOffset
と入れます。レイヤー名やscrollOffsetは入力欄右の+から選択できるので、文字入力する必要はありません。
これはすなわち「コンテナー 1のスクロールした量」を「140.5にプラスする」という意味です。140.5というのはスクロール量が0の場合に移動する位置です。基準点を画像の中心にしたため、画像の高さの半分が移動すべき位置になっています。ProtoPieの数式では、スクロール量だけではなく位置や大きさなどいろいろ取れるので、140.5のような数字を直打ちせず下記のように数式のみで表現することもできます。
(が、長いので採用するかはお好みで。)式としては、スクロールコンテナの幅に、画像のアスペクト比をかけて拡大される高さから移動すべき座標を出してそれにスクロール量を足しています。
(`コンテナー 1`.width * `Content1`.height / `Content1`.width) / 2 + `コンテナー 1`.scrollOffset
これを3つのコンテンツのMoveに反映させると、どの位置からでも画像がスクリーン上部に動きます。
クリックした画像を別シーンに伝える
現状、どのコンテンツをタップしても遷移先は同じコンテンツなので、これをなんとかします。
遷移先シーンに「何をタップしたか」を伝えるには変数が使えます。タップしたコンテンツの番号を変数に入れ、遷移先でその変数の番号を参照して、画像を出し分けるようにします。
変数は画面左下のエリアで設定できます。+をクリックして「全てのシーンで使用」を選択し、変数を作成します。
変数名はデフォルトで「variable1」になっているので、分かりやすいものに変えましょう。ここでは「contentIndex」にしておきます。変数には数字、テキスト、カラーのいずれかを入れることができますが、今回はデフォルトの数字で大丈夫です。
また変数名の右側に虫のようなマークがありますが、これをクリックするとプレビュー中、変数に何が入っているのかを確認できるので便利です。
ここからはいつものように
– シーンHome –
- Content1のTapトリガーにAssignのレスポンスを追加。変数名はcontentIndexを選択、数式に0を入力。
- Content2のTapトリガーにAssignのレスポンスを追加。変数名はcontentIndexを選択、数式に1を入力。
- Content3のTapトリガーにAssignのレスポンスを追加。変数名はcontentIndexを選択、数式に2を入力。
数式にそれぞれ0 1 2を入れましたが、バラバラであればなんでもOKです。
– シーンDetail –
- StartトリガーにConditionを追加。contentIndex、=、数値、0をそれぞれ入力。(content1が0だったらこのCondition以下のレスポンスを実行するという意味)
- Conditionの下にOpacityを3つ追加し、Header1は不透明度100 Header2 Header3の不透明度を0
- その下にさっき作ったConditionをコピペ、先ほど0だったところを1に
- 今追加したConditionの下のOpacity3つに対し、Header2は不透明度100 Header1 Header3 は不透明度0
- 最後のConditionを追加、数値を2に
- 今追加したConditionの下のOpacity3つに対し、Header3は不透明度100 Header1 Header2 は不透明度0
- 追加したOpacityの時間は全て0に
以下のようなStartの中身になるかと思います。ちなみにレスポンスの名前は変えられるので分かりやすく変えてもいいです。非表示になっているレイヤーは表示した上でOpacityをかけて下さい。
これで遷移は綺麗に画像がつながるようになりました。あとはスクロール時の画像のブラーや、タイトルの変更などもちまちま設定すると、よりそれっぽくなります。
補足
紹介しきれなかった便利な機能として、Detectトリガーというのがあります。変数の値やレイヤーの動きなどを監視し続け、変化があった時に呼ばれるものです。ショッピングカートの数量カウンターなどを作る時に、変数に数字を足していき、変数の数字が変化したらテキストの表示も変化させるなどに使えます。
番外編 – ゲームを作る
正直ProtoPieはゲームを作るのには適していないです。当たり判定が取れなかったり、自作関数に指示をまとめられないためです。が、Conditionや変数、Detectを駆使すればできないこともないです。ということで作ってみました。割とProtoPieの機能の粋を集めたものになってます。
https://share.protopie.io/KqumNS351xg
4. おわりに
長々とProtoPieでできることを書いてきました。プロトタイピングツールを使いこなすことによって、関係各所とのコミュニケーションがスムーズになり、プロダクトの精度が上がることは間違いないです。
その一方で、「何が良いインタラクションなのか」を判断するために、感性や、人間の心理に関する知識が必要だということにも気づきます。
それを身につけるためには数を作って経験を積むことが最も大切だとは思いますが、知識の面では参考になる文献もあります。スマホのUIデザインに関しては
がやはり鉄板です。それぞれインタラクションやアニメーションに関する記述があります。
さらに個人的にお気に入りの文献は
があります。とても為になるのでぜひ読んでみてください。「イージングをInにすべきかOutにすべきか」みたいな判断はこの辺りで得られる気がします。