Tomomi ❤ Imura

PolymerでMaterial Designなチャットアプリを作ろう

今年注目のオープンWebテクノロジーのひとつに、Web Componentsが挙げられると思います。HTML5Experts.jpでも今まで幾度も関連記事、Polymer.jsについての記事が紹介されてきました。今回は実際に、PolymerとMaterial Designのデザインコンセプトを用いて、視覚的にもユーザエクスペリエンスにも優れたチャットアプリを実際に作ってみましょう。

Material Design and Polymer

まず始める前にこのライブデモ、Kitteh Anonymousをデスクトップまたはモバイルのモダンブラウザで実際に試してみてください。ここでは、このデモの簡略版であるLiteバージョンを実際に作成する方法をステップ・バイ・ステップで紹介したいと思います。

必要な知識

  • Polymerの基礎知識
  • パッケージマネージャ、Bowerの基本的な使い方(Polymerと依存するファイルをインストール、アップデートするのに使いますが、必ずしも使う必要はありません)

泉水翔吾さんの記事、Web Componentsを簡単・便利にするライブラリ「Polymer」を使いこなそうや、佐藤歩さんの話題のMaterial DesignをWebで実現!Polymerで「Paper Elements」を試そうを先に読むのをおすすめします。

PolymerとWebスタンダード

ちまたに数多く存在する、JavaScript UI library。Polymerも単にまたそのひとつ、と思うかもしれません。しかしPolymerが他と違うのは、これがW3C WebプラットフォームプリミティブのWeb Componentsを基礎に作られていることです。このWeb Componentsファミリーに含まれるものに

などが挙げられます。

そしてPolymerに含まれる webcomponents.js は W3C DOM4のDOM mutation observersや ECMAScript standardsである Object.observe() のPolyfillの役目を果たしています。

レゴブロックのようにWebを構築しよう

lego Polymer webコンポーネントはカプセル化された何度も再利用できるコンポーネント。まるでレゴで家を構築するかのように、既存のパーツを使ったり自分で組み立てたパーツを使ったりと、いろいろなパーツを組み合わせてWebアプリを作ることができます。

実際にPolymerでアプリを作るには、まず必要な要素をインポートしてから使うことになります。

Material DesignとPolymerの関係

Material Designは、既存のどのスクリーンサイズやデバイスにでも対応できる、ビジュアルとインタラクションデザインにすぐれたデザインスペックで、もともとはAndroid 5.0 Lollipop用にデザインされたものが、のちにWeb用としてPolymerのPaper Elementsとして適応されるようにました。

1. Paper Elementsを使ってみよう

さて実際にこれらを使って自分のアプリを作ってみましょう。 まず、Polymerをインストール、そしてアプリ構築に必要なコンポーネントをインポートします。

1.1. Polymerをインストール

$ bower install --save Polymer/polymer

これで必要最低限のファイルがそろいます。

polymer file structure

インストールが終わったら、index.htmlの <head> セクションに、 webcomponents.min.js のみをロードさせます。

1.2. UI コンポーネントをインポート

このデモのUIには、いくつかのPolymer CoreとPaper Elements、そして自作のカスタム要素が使われています。

  1. core-scaffold (レスポンシブレイアウトを構成するheader、toolbar、menuなどがすでに揃った骨組み)
  2. core-item
  3. paper-input
  4. paper-fab
  5. カスタム (のちに作成しましょう)

polymer paper elements

Bowerを使って4つのcomponentsをインストールします。

インストールが終わったら、これらをHTML importsを使ってインポートします。

このようにすることで、これらの要素がDOM上で使われる前に依存ファイルを含めて全てがしっかりロードされることになります。

1.3. ベーシックUIの構成

まず、 <core-scaffold> を使って、ベースとなるレイアウトを構成しましょう。この要素は、レスポンシブな骨組みを簡単に作る(scaffold)ことができる便利な要素で、サブコンポーネントとして <core-header-panel><core-toolbar><core-drawer-panel> などがすでに含まれています。

これでアプリのコア・ストラクチャーができました。 <core-scaffold> は実際はこの例よりもより簡単に使うとこができるのですが、このデモでは左のドロウアー部分のヘッダの高さをかえて、ベーシックスタイルよりも少し凝ったデザインにしています。

ここで <body> に見慣れない属性が使われていることにお気づきかと思います。 この fullbreed はbodyをビューポートにぴったり合わせるため、 unresolved はスタイライズされていないコンテンツが一瞬画面に表示される現象(FOUC)を防ぐために使われています。

他、要素の要所に flex 属性が使われています。PolymerはCSSスタンダードのFlexboxを属性として使っており、この子要素に layout horizontal | vertical が使われた時、この子要素が横または縦に、スクリーンにある分だけのスペースに引き伸ばされます。下の図を見てください。ヘッダUIのタイトル部分が引き伸ばされているため、右のアイコンと数字がきれいに右端に寄せて表示されています。

flex

1.4. 個々のUI Elementsを使う

次に、このベースレイアウトの中に、先ほど一緒にインポートした個々のUIパーツを使います。 例えば次に示すコードサンプルでは、スクリーン横幅にあわせスタイライズされたインプットと、送信ボタンを表示しています。

二重カーリーブラケットに囲まれた {{input}}{{sendMyMessage}}に注目してださい。これは式や on-で始まるイベントハンドラとして使われます。次のチャプターで簡単に説明します。

実際のアプリの中でコンポーネントがどのようにインポートされているかは、GitHub Repo上のlite.htmlのソースコードを見て確認してみてください。

1.5. データバインディング

PolymerはHTMLの新スタンダードである <template>を使って、宣言的で双方向のデータバインディングをサポートしています。 Polymerのデータバインディングにはいくつか方法があるのですが、ここでは <template> でアプリの全コードを囲むことによって自動バインディングを可能にしています。

これで、前チャプター(1.4)で既出の paper-input の例にあるように、ユーザが入力する値を {{input}}を使って得ることができます。

他、このデータモデルを使えば、要素を繰り返し使うようなマークアップを簡略化するなどということもできるのです。 実際にドロウアーパネルUIの中に、 core-itemを使ったリストを作成してみましょう。

core-itemのコンテンツは、JavaScript側で、items配列を使ってオブジェクトで指定します。 ここでは、 <core-icons>で既に用意されているアイコンのセットを使っています。

これで、モデルを生成・変更した時に自動的にテンプレートにインスタンスが生成され、DOM上には下の図のように表示されます。 core-item

2. カスタム要素の作成

メインUIとなる部分にチャットの会話を表示させましょう。このUIパーツには、アバター、ユーザーID、チャットのテキストが表示させるようにしたいのですが、Polymer CoreにもPaperにもそういったバーツは存在しません。ですので自分でカスタム要素を作ってみましょう。

まず新規のHTMLファイルを作成します。ここではこのファイル名を、 x-chat-list.htmlとします。

このカスタム要素は、属性、 avatarcolorusernametextを扱います。

custom element

ここでは、カスタム要素の作製法を一から説明はしませんが、簡略化されたカスタム要素は次のようになります。

この例ではわかりやすく見せるために、 <style>...</style>部分が省略されていますが実際にUIのカスタム要素を作るにはCSSは不可欠でしょう。CSSを含む全ソースコードの x-chat-list.htmlGitHub Repoで見てください。

できあがったら index.htmlに戻って、このカスタム要素をインポートします。

データは実際の生のチャットの会話を、PubNubデータ・ストリームサービスを使って表示させます。詳しくは次のセクションで説明します。

かなりはしょってしまいましたが、カスタム要素を作る詳しい説明は公式のドキュメントを参照してください。

3.PubNub Elementでメッセージの送信・受信をする

pubnub-element

アプリのUI部分はすべて完成しましたので、今度はチャットルームそのものを作ってみましょう。データの送受信はPubNubが提供するリアルタイム・データストリームのPolymerエレメント版である、 <pubnub-element> を使います。 今まで使った要素と違うのはこの要素にはユーザインターフェイスが伴わないことです。では何をしてくれるのかというと、要素でカプセル化されたPubNub APIがクラウドでデータのpublish / subscribeのやりとりをはたしてくれるのです。なので私たちがサーバを立てる必要はありません。

<pubnub-element>はサードパーティAPIを使用しますので、まず自分のAPI keysを作成しておく必要があります。 PubNubアカウントはここから取得してください。短時間試してみたいだけならば、 publish_keypublish_keydemoにして使うこともできます。

3.1. <pubnub-element>をインストール・インポート

インストールは、他の要素同様にBowerを使うことができます。

$ bower install --save pubnub-polymer

インストール後は index.htmlでこれをインポートします。

3.2. <pubnub-element>を使う

まず、 <core-pubnub>を使ってクライアントの初期化をします。

ここで使われる uuidとはチャットルームの各ユーザのユニークIDで、ランダムな文字列を使います。このアプリでは、おのおののユーザがアクセスした時に、navy-siamese(濃紺色・シャム猫)のように、色と猫の種類の文字列の組み合わせで構成されたIDが与えられるようにします。

cat avatars

3.3. メッセージの送信

<core-pubnub-publish>はチャンネルのサブスクライバー全てにメッセージを送信することができる要素です。

では、ユーザが文字を入力して送信ボタン( <paper-fab> )をタップした時に、そのメッセージをサーバに送るコードを書きましょう。 Polymerは、 on-*イベントハンドラを使うので、この場合 on-tapイベントを用いて <paper-fab>がこのアクションを引き起こすことができるようにしてみます。

これでユーザの情報とメッセージテキストが、サーバに送られました。次はすべてのユーザがこれを受信して、内容ををDOMに表示させてみましょう。

3.4. 受信データのリアルタイムバインディング

ネットワークに送られたメッセージは <core-pubnub-subscribe>要素を使ってクライアント側で受信することができます。

ここでの messages属性は受信されたメッセージオブジェクトの配列が含まれています。ではここで受け取ったデータを先ほど作成した <x-chat-list>カスタム要素を使って表示させましょう。 実は先のチャプター2で、既に messages 配列のインスタンスが使われていることに気がついたでしょうか? messages="{{messages}}" 属性が< core-pubnub-subscribe><x-chat-list>の間で双方向バインディングがすでに行われているのです。なので、自動的にDOM生成を行ってチャットの内容を表示することができるのです!

ではもう一度、 <x-chatlist>を見てみましょう。

メッセージが受信された際には、 <core-pubnub-subscribe>のコールバック、 on-callbackが発生します。 このチャットの配列は時間順に並べられているので、新しいメッセージはスクリーンの一番下に表示されることになります。これではユーザの使い勝手が悪いので、コールバック発生時に自動的に最新チャットまでスクロールさせることにしましょう。

これで、PolymerでMaterial Designの美しいデザインを使った簡単なチャットルームが完成しました!

このチュートリアルではわかりやすくするために、デモで使われているすべてのフィーチャーについてや、Shadow DOMのスタイリングについての説明は省略してあるので、さらに知りたい方は是非、GitHub のRepoで確認してみてください。

デモとチュートリアル、楽しんでいただけたなら幸いです!Happy coding!

polymer pubnub chat app animated gif

de:code 2017
Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Canvas Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Node.js PhoneGap Polymer React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket