Tutorials

15

分で読める

How to Prototype a Search Bar

Prototype a fully-functioning search field / bar with ProtoPie’s "indexOf" and "lowerCase" functions.

Jeff Clarke、 UX Designer & ProtoPie Educator

概要

ほとんどすべてのデジタル体験には何らかの検索体験があり、いつかはその体験をプロトタイプ化する必要が出てくる可能性が高いです。動作する検索バーは多くのプロトタイピングツールの能力を超えており、デザイナーである私たちは、さまざまな代表的な状態における検索体験の見た目をいくつかのスクリーンショットで見せることで、その体験を疑似的に再現することがよくあります。

💡 この制限は ProtoPie にはありません!

ProtoPie の高度なコード不要のロジックモデルにより、真に機能する検索バー体験をすばやく簡単に作成できます。さらに、多くのプロトタイピングツールには視覚スタイルを再利用するためにコンポーネントを作成できる機能がありますが、ProtoPie ではそれをさらに進め、インタラクションも再利用できるようにし、このチュートリアルではより重要なロジックも再利用できるようにしています。

下のデモを見て、何が作れるか確認してみましょう。


prototype that includes a functioning search bar


検索バーのプロトタイプ

開始用 Pie ファイル完成版 Pie ファイル

概要

  • 学べること

  • 始める前に

  • ステップごとのガイド

  • パート 1: 検索を設定する

  • パート 2: 検索バーに結果を表示する

  • パート 3: 検索を大文字・小文字を区別しないようにする

  • パート 4: 結果を折りたたむ

  • なぜこれで動くのか?

  • これで完了です! Pie のように簡単!

  • 完全に機能する検索バーでプロトタイプをレベルアップ

学べること

このチュートリアルを終えるころには、次のことを学べます。

  • 組み込みの indexOf()lowerCase() 関数の使い方。

  • コンポーネント同士をシーンやお互いと連携させる方法。

  • 再利用可能なロジックをコンポーネントに組み込む方法。

  • 動作する検索体験をどれだけすばやく簡単に作れるか。本当にそうです! これがどれほど簡単か、きっと驚くはずです!

所要時間: ≤15 分

始める前に

まず、開始用の Pie ファイルを開きます。これは 8 曲の一覧を持つモックの音楽アプリです。リストの上部に検索ボックスがあります。リスト内の各曲は コンポーネント「Song」のコピーです。すべての構造が同じなので、コンポーネントとして作成されています。

作業を 8 回複製する代わりに、コンポーネントを使って構造を一度だけ作成し、それをシーン内で 8 個コピーして、それぞれでカバーアート、曲名、アーティストをカスタマイズしました。

検索バーを機能させるために、シーン内と Song コンポーネントのマスターコピーの両方で作業していきます。

ステップごとのガイド

パート 1: 検索を設定する

まずは、メインシーンの検索バーにいくつかのインタラクションを追加するところから始めましょう。

  • Search field の入力レイヤーに Detect トリガーを追加します。検出するプロパティとして Text を選択してください。


Add a Detect Trigger to the Search Field input layer


Detect トリガー

  • Send Response を追加します。Channel には「Send to Current Scene」を選択してください。メッセージには SEARCH を使い、「Send Value Together」のチェックボックスをオンにします。表示されたボックスには次の式を使います: ``Search field.text


Add a Send response


Send Response

💡 何が起きているの?

Detect トリガーは、検索ボックスのテキストプロパティの値が変わるたびに発火します。キーを押すたびに、メッセージ SEARCH が検索ボックスの内容と一緒にシーンへ送信されます。このメッセージを受け取るように設定されたものは、それを受信して応答できます。次にそれを行います。

曲リストの各項目をコンポーネントにしておく利点は、マスターコンポーネントの 中に ロジックを置けるため、それが すべて のコピーに含まれることです。こうすることで、各コンポーネントが検索に一致するかどうかを個別に判断できるようになります。

  • Song コンポーネントのマスターコピーへ移動します。


Go to the Component Scene


コンポーネントのシーン

今、Song コンポーネントのマスターコピーを編集しているので、ここで行う作業はメインシーン内のすべてのコピーに自動的に複製されます。コンポーネントを SEARCH メッセージに反応させましょう。

  • Receive トリガーを追加します。Channel には「Receive from Current Scene」を選択してください。メッセージは SEARCH を使います。「Assign to Variable」のチェックボックスをオンにします。コンポーネントにはまだ変数がないので、新しく作成する必要があります。


Add a Receive trigger


Receive トリガー

💡 Receive トリガーを設定するときは、メッセージと、それが受信されるチャンネルの両方が、対応する Send Response で使った内容と一致している必要があります。

  • コンポーネント内に変数を作成し、searchKeyword と名付けます。タイプは必ず Text に設定してください。


Create a variable called searchKeyword


searchKeyword という変数を作成する

  • 前のステップで作成した Receive トリガーに戻り、「Assign to Variable」の下で、先ほど作成した searchKeyword 変数を選択します。


Choose the newly created variable under assign to variable


Assign to Variable の下で新しく作成した変数を選択する

💡 Pie が値付きのメッセージを受信したら、その値をまず変数に割り当てる必要があります。そうしないと、それを使うことができません。ここで私たちが行っているのは、Assign to Variable を選ぶことです。

パート 2: 検索バーに結果を表示する

Song コンポーネントが、シーンから検索キーワードを受け取るように設定できました。次は、そのキーワードが曲名のどこかに一致するかどうかを判定したいと思います。

条件式では、ProtoPie の組み込み関数 indexOf() を使います。indexOf() は、あるテキストの中に別のテキストが含まれているかどうかを調べます。これは sourcesearchValue の 2 つのパラメータを使って動作します。

  • source は、検索対象のテキストです。今回の場合は曲名です。

  • searchValue は、source の中で探したいキーワードです。これは searchValue 変数に渡した値になります。

indexOf() を実行すると、見つかったテキストの位置を示す数値、または一致が見つからなかった場合は -1 が返されます。私たちが注目するのは 2 つの可能性です。

  • 関数が -1 を返した場合、それは曲が検索に一致しないという意味なので、検索結果から除外する必要があります。

  • 関数が -1 以外の何かを返した場合、その曲は検索に一致しており、結果に含める必要があります。

それでは、indexOf() の動きを見てみましょう!

  • 引き続き Song コンポーネントのマスターコピーで、Receive トリガーの下に条件を追加します。

  • この条件では、まず 1 つ目の可能性、つまり一致しない場合を確認します。

  • 最初のドロップダウンで「Formula」を選択します。

  • 次の式を使って OK をクリックします: indexOf('``Title'``.text, searchKeyword)

  • 演算子は =(等しい)のままにし、下のボックスに -1 を入力します。


Use ProtoPie’s built-in indexOf() function in our condition


条件で ProtoPie の組み込み indexOf() 関数を使う

💡 Operator は、ProtoPie に対して比較をどのように行いたいかを指示します。条件の中央にあるアイコンの列 — > ≥ < ≤ = ≠ — を見てください。これらが ProtoPie で使えるすべての演算子です。

  • 一致しないときは、その曲を非表示にします。条件の下に Opacity Response を追加してください。Song レイヤーを選択します。これはコンポーネントの最上位コンテナです。opacity を 0、duration を 0 に設定します。duration を 0 にすると、不透明度の変化がアニメーションされず、即座に起こります。


Add an Opacity Response under our condition


条件の下に Opacity Response を追加する

次に 2 つ目の可能性、つまり検索に一致する場合を考えます。

  • もう 1 つ条件を追加します。上側には同じ式を使います: indexOf('``Title'``.text, searchKeyword)

  • 今回は (等しくない)演算子を選びます。値には再び -1 を使います。


Add another condition under the Receive trigger


Receive トリガーの下にもう 1 つ条件を追加する

より分かりやすくするために、条件の名前を変更しましょう。

  • 最初の条件をダブルクリックして、NO MATCH に名前を変更します。

  • 2 つ目の条件をダブルクリックして、MATCH に名前を変更します。


Let’s rename our conditions
  • 条件の名前を変更しましょう*

ここまでで、検索は動作するはずです。メインシーンに戻りましょう。

  • プレビューしてみてください。入力していくと、検索語に一致しない曲が消え、バックスペースで再び表示されるはずです。


Preview of search bar prototype in the preview window


プレビューウィンドウで作業を確認する

ほんの数ステップで、動作する検索体験の基礎ができました!

確かに 動作 はしていますが、おそらく問題にも気づいたはずです。大文字の「C」で検索すると、3 曲が表示されたままになります。しかし小文字の「c」で検索すると、結果は 0 件になります。


Search bar prototype shows different search results for lowercase and uppercase letters


小文字と大文字で異なる検索結果

これを修正しましょう!

パート 3: 検索を大文字・小文字を区別しないようにする

indexOf() 関数を使うと、大文字・小文字は区別されます。Cc と同じではない、という扱いになります。しかし、これをそのままにしておくのは、あまり良い体験とは言えません。

これを解決するには、式から大文字・小文字の区別を取り除く必要があります。私たちの方法は、indexOf() を実行する前に、検索キーワードと曲名の両方を小文字に変換することです。

ProtoPie には、lowerCase() という別の組み込み関数があります。名前のとおり、テキストを小文字に変換します。たとえば lowerCase("ProtoPie is the BEST!!")protopie is the best!! を返します。

それでは、lowerCase() の動きを見てみましょう!

引き続きメインシーンで、Detect トリガーの下にある Send Response を修正しましょう。

  • 「Send Value Together」の下のボックスで、既存の式を次のように lowerCase() 関数を使う形に変更します: lowerCase('Search field'.text)。こうすることで、検索バーに入力した内容の小文字版をすべてのコンポーネントが受け取れるようになります。


Modified existing formula to use the lowerCase() function


既存の式を lowerCase() 関数を使う形に変更する

💡 lowerCase() 関数名の大文字の「C」に注目してください。関数名も大文字・小文字を区別します。小文字の「c」を使って lowercase() と入力してしまうと、式は動作しません。

indexOf() を実行する前に、Songtitle に対しても同じことを行う必要があります。

  • もう一度、Song コンポーネントのマスターコピーを編集します。

  • 2 つの条件の両方を修正する必要があります。最初の条件をクリックして、式を次のように変更します: indexOf(lowerCase('Title'.text), searchKeyword)


first condition


最初の条件を修正する

**💡 何が起きているの? **

関数は別の関数の中にネストできるため、別の関数のパラメータとして使うことができます。

indexOf() 関数は最初のパラメータとして Text を期待しているので、Text を出力するどんな関数でも使えます。lowerCase() 関数はそれに当たります。関数がこのようにネストされている場合、内側の関数が外側の関数より先に実行されます。その結果、indexOf() は小文字に変換された曲名を使って動作します。

  • 2 つ目の条件の式にも同じ修正を加えます。


second condition


2 つ目の条件を修正する

メインシーンに戻って、もう一度プレビューしてください。これで検索は大文字・小文字を区別しなくなるはずです。

パート 4: 結果を折りたたむ

検索は完全に機能するようになりましたが、一致しない曲があった場所には空白が残っています。表示されるときに結果を詰めて表示したいところです。

メインシーンからコンポーネントへメッセージを送れるのと同じように、コンポーネント同士もメッセージを送信できます。ただし、その前に、お互いを区別できるようにコンポーネントを修正する必要があります。

  • Song コンポーネントのマスターコピーを編集します。

  • id という変数を作成します。デフォルトの Number 型のままにしてください。「Make Overridable」と書かれたチェックボックスをオンにします。


variable called id


id という変数を作成する

💡 「Make Overridable」にチェックを入れることで、シーン内の各コンポーネントコピーが id に異なる値を持てるようになります。

  • メインシーンに戻ります。各 Song コンポーネントのコピーには、右側のプロパティパネルに「Overrides」というセクションがあり、先ほど作成した id 変数を編集できるようになっていることが分かります。


The Overrides section in the property panel


プロパティパネルの Overrides セクション

  • 各コンポーネントのコピーに異なる id の値を設定します。連番を使ってください。

  • 例: 1 つ目の「The Celebrated Ways」には 1 を設定

  • 2 つ目の「Feel Again」には 2 を設定

  • 3 つ目の「Good Enemy」には 3 を設定

  • 以下同様です。


Give each component a different value for id


各コンポーネントに異なる id の値を設定する

💡 この連番は、ロジックにおいて非常に重要になります。

幸い、コピーのレイヤー名は、id が持つべき値と対応しています。Song 1id:1Song 2id:2、というように、Song 8 までしっかり確認してください。

さあ、マジックを起こしましょう!

  • 再び Song コンポーネントのマスターコピーを編集します。

  • 「NO MATCH」条件の下に Send Response を追加します。Channel には「Send to Current Scene」を選択してください。メッセージには REORDER を使います。「Send Value Together」のチェックボックスをオンにし、その下に表示されたボックスには id の式を使います。


Send Response under the condition


条件の下に Send Response を追加する

  • hiding_id という新しい変数を作成します。デフォルトの Number 型のままにしてください。


new variable called hiding_id


hiding_id という新しい変数を作成する

  • 「NO MATCH」条件の下に Send Response を追加します。

  • Receive トリガーを追加します。Channel には「Receive from Current Scene」を選択してください。メッセージには REORDER を使います。「Assign to Variable」の横のチェックボックスをオンにします。

  • Receive トリガーでは、「Assign to Variable」の下で新しく作成した hiding_id 変数を選択します。


hiding_id variable


hiding_id 変数を選択する

続ける前に、ここで何が起こるかを説明しておくことが重要です。

「NO MATCH」条件の中の Send Response を使って、メッセージ REORDER をブロードキャストしています。もしコンポーネントが会話できたら、この Song コンポーネントの特定のコピーが、他のすべてのコピーに対して「私は id:x. です。検索に一致しないので非表示になります。ほかのすべてのコンポーネントはそれに合わせて並び替えてください。」と言っているようなものです。

この時点で、メッセージを送ったコピー自身を含め、Song コンポーネントのすべてのコピーがそのメッセージを受信します。また、元々メッセージを送信したコンポーネントの id も一緒に送信され、それが hiding_id という変数に割り当てられます。Receive では、各コピーが自分自身の idhiding_id を比較します。

ここが重要です:

受信側の id が送信側の id より大きい場合(つまり id > hiding_id)、受信側の位置を 1 つ上のスロットへ移動させます。各曲に id の値を連番で設定したのは、このためです。

では、実際に見てみましょう。

  • Receive Response の下に条件を追加します。最初のドロップダウンで変数 id を選択します。>(より大きい)演算子をクリックします。下のドロップダウンで hiding_id 変数を選択します。


Condition under the Receive Response


Receive Response の下に条件を追加する

  • その条件の下に、Song レイヤーへの Move Response を追加します。「Position」ドロップダウンで「Move By」を選び、Y ボックスに -84 を入力します。最後に、これがアニメーションしないように duration を 0 に設定します。


Added Move Response to the Song layer


条件の下に Song レイヤーへの Move Response を追加する

これでやるべきことは完了です。メインシーンに戻ってプレビューしてください。検索は完全に動作するはずです!

なぜこれで動くのか?

まだ少し仕組みが分かりにくいようなら、ロジックをおさらいしましょう。上記の内容がすべて理解できているなら、読み飛ばしても大丈夫です。

Hide、Reset、Reorder は毎回のキー入力で発生する

検索バーに文字が入力されるたびに、すべてのコンポーネントが、その文字が以前に一致していたかどうかの記憶なしに、検索に一致するかを判断します。一致したら、すでに表示されていて元の位置にあっても、自分自身をリセットします(位置と不透明度の両方)。一致しない場合は、すでに非表示でも自分自身を隠します。自分を隠す項目は、REORDER メッセージを自分の id と一緒にブロードキャストし、その下にあるすべてのコンポーネント(たとえば、非表示にしたコンポーネントより大きい id を持つもの)を 84 ピクセル上に移動させます。

例を見てみましょう。ここでは最初の 3 曲だけを見て、残りは無視します。

  1. 「The Celebrated Ways」

  2. 「Feel Again」

  3. 「Good Enemy」

ユーザーが検索バーに n を入力したとします。次のことが起こります。

  • Song 1 は一致せず、自分自身を隠します。

  • Song 1 は id の値とともに、すべてのコンポーネントへ REORDER をブロードキャストします。

  • Song 2 は一致し、自分自身をリセットします。

  • Song 2 は Song 1 から REORDER を受信し、1 つ目のスロットに移動します。

  • Song 3 は一致し、自分自身をリセットします。

  • Song 3 は Song 1 から REORDER を受信し、2 つ目のスロットに移動します。

次に、ユーザーが検索バーに入力し続けたとします。次の文字は e で、検索語は ne になります。次のことが起こります。

  • Song 1 は一致せず、すでに隠れていても自分自身を隠します。

  • Song 1 はすべてのコンポーネントへ REORDER をブロードキャストします。

  • Song 2 は一致せず、自分自身を隠します。

  • Song 2 はすべてのコンポーネントへ REORDER をブロードキャストします。

  • Song 2 は Song 1 から REORDER を受信し、1 つ目のスロットに移動しますが、非表示なので見えません。

  • Song 3 は一致し、自分自身をリセットして、元の 3 番目の位置に戻ります。

  • Song 3 は Song 1 から REORDER を受信し、2 つ目のスロットに移動します。

  • Song 3 は Song 2 からも REORDER を受信し、さらにもう一度 1 つ目のスロットに移動します。

これで完了です! Pie のように簡単!

動作する検索体験を作る中で、ProtoPie の最も強力な機能をたくさん使いました。

  • 関数と式

  • indexOf()lowerCase() 関数の使い方を学びました。

  • 式の中でそれらを入れ子にして、情報を複雑に操作する方法を学びました。

  • Send & Receive

  • Send と Receive を使って、メインシーンがすべてのコンポーネントと通信できるようにし、さらにコンポーネント同士も通信できるようにしました。

  • 機能的なコンポーネント

  • コンポーネントは見た目のスタイル面で再利用できるだけでなく、機能面でも再利用可能にしました。実際、Song コンポーネントがこの体験の実現に必要な作業のほとんどを担っています。

何よりも、これがどれほど簡単に動作させられるかを実感していただけていれば幸いです。使ったのはほんの数個の組み込み関数だけで、そして最も重要なのは、コードがまったくないこと!

完全に機能する検索バーでプロトタイプをレベルアップ

検索、クリック、そして驚きの準備はできましたか? それなら ProtoPie を始めて、検索バーのチュートリアルに従い、シームレスなユーザー体験を作成しましょう。

無料で始める

プロトタイピングについてもっと学びたいですか?

[役に立ちましたか?お知らせください!]