このcodelabでは、Polymer3を使ったカスタムエレメントの作り方について学べます。ボタンをトグルする簡単なPolymerエレメントを作ります。完成イメージは以下のような感じになります。
これは以下のような簡単なマークアップで利用可能になります。
<icon-toggle></icon-toggle>
このcodelabでは、Polymerを使って作業するための重要なコンセプトについても紹介していきます。
もし全てのコンセプトについて理解できなくても心配しないでください。それらの内容はPolymerの公式ドキュメントにより詳しく書かれています。
チュートリアルを始める前に、以下のソフトウェアがあることを確認してください:
以下の項目について、基本的なスキルや知識が必要になります:
Gitはバージョン管理ツールです
git --version
インストールが成功していれば、Gitのバージョンが表示されるはずです。
もしGitのバージョン番号がgit version 2.18.0
のように表示されない場合は、次のリンクを参照してみることをおススメします。公式ドキュメント - Gitのインストール.
NodeはJavaScriptの実行環境です。npmはNodeのパッケージ管理ツールです。これらはNodeをインストールすると両方ともインストールされます。
npm install npm@latest -g
現時点で node -v
は v8.10.0
でした
現時点で npm -v
は 5.8.0
でした
バージョン番号が表示されなかったら 公式ドキュメントのインストールガイドを参照してください
次のコマンドでリポジトリをクローンしてください。
git clone https://github.com/Polymer-Japan/polymer3-first-element.git
ディレトリをクローン先に移動してから、npmコマンドで依存するパッケージをインストールします。
cd polymer3-first-element npm install
インターネット回線が遅いと、とても時間がかかる場合があります....
インストールが終了すると、以下のようなディレクトリ構造になります。
作業する主なファイルはicon-toggle.js
です。このファイルにはカスタムエレメントの定義が入っています。
デモの実行方法はとても簡単です。まだアプリは何も実装していませんが、以下のコマンドを実行してみましょう。
npm start
すると、Polymerの開発サーバーが動いて、デモがブラウザ(chrome)の新しいタブで開きます。アイコントグルは表示されず、テキストだけが表示されるはずです。どうってことないかもしれませんが、これで全てがうまく動いていることが確認できます。
次に、画面にアイコンを表示するための簡単なエレメントを作ってみましょう。
このステップでは、以下のようなことを学習できます。
エディタでicon-toggle.js
ファイルを開いてください。このファイルにはカスタムエレメントのスケルトンが入っています。
既存コードを見ながら進めましょう。
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icon/iron-icon.js';
キーポイント:
import
はES6 Module importです。アプリケーションで利用するエレメントやモジュールをインポートします。iron-icons
と iron-icon
をインポートします。これらは、この後で登場します。次はエレメント自体を定義していきます。
class IconToggle extends PolymerElement {
static get template() {
return html`
<style>
/* local DOM styles go here */
:host {
display: inline-block;
}
</style>
<!-- local DOM goes here -->
<span>Not much here yet.</span>
`;
}
}
キーポイント:
PolymerElement
を継承したクラスを作成します。template
プロパティを定義します。例えばtemplate
というstatic getterが使えます。エレメントが初めてインスタンス化されると template が呼び出されます(つまり2度目のインスタンス化では呼び出されません)。html
ヘルパーを使うとJavaScriptのテンプレートリテラルから HTMLTemplateElement インスタンスを生成できます。(html
ヘルパーは polymer-element.js
モジュールからインポートできます)template
内の<style>
エレメントを使うと、Shadow DOMにscopedな(カプセル化された)スタイルを定義できます。これはドキュメントの他の部分には影響を及ぼしません。:host
擬似クラスは、定義するカスタムエレメントそのもの(この場合は<icon-toggle>
エレメント自体)です。
window.customElements.define('icon-toggle', IconToggle);
キーポイント:
customElements.define
メソッドの第二引数にエレメントクラスを指定します。エレメントの基本構造にふれたところで、Shadow DOMテンプレートを編集してみましょう。
local DOM goes here
というコメントの後に書いてある<span>
タグを見つけてください。
<!-- local DOM goes here -->
<span>Not much here yet.</span>
`;
<span>
タグを、以下のように<iron-icon>
に置き換えてみてください。
<!-- local DOM goes here -->
<iron-icon icon="polymer">
</iron-icon>
`;
キーポイント:
<iron-icon>
エレメントはアイコンを表示するカスタムエレメントです。今は "polymer" という名前をハードコーディングしています。Shadow DOMで利用できる新しいCSSセレクターがいくつかあります。icon-toggle.js
ファイルの:host
セレクターはすでに紹介しました。これは<icon-toggle>
エレメントそのもののスタイルを指定します。
<iron-icon>
エレメントのスタイルを指定するために、<style>
タグ内のCSSを以下の内容に書き換えてください:
<style>
/* local styles go here */
:host {
display: inline-block;
}
iron-icon {
fill: rgba(0,0,0,0);
stroke: currentcolor;
}
:host([pressed]) iron-icon {
fill: currentcolor;
}
</style>
キーポイント:
<iron-icon>
タグはSVGアイコンを使っています。fill
やstroke
は、SVG固有のCSSプロパティです。アイコンの塗りつぶしと輪郭の色をそれぞれ設定します。:host()
関数は、引数で指定されたセレクタが一致するホスト要素(エレメント)に適用されます。このときの[pressed]
は標準のCSS属性セレクタで、icon-toggle
エレメントにpressed
属性が設定されている場合に、スタイルが適用されます。これまでの修正で、カスタムエレメント定義は以下のようになっていると思います。
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icon/iron-icon.js';
/**
* `icon-toggle`
* Get started creating custom elements with Polymer 3
*
* @customElement
* @polymer
* @demo demo/index.html
*/
class IconToggle extends PolymerElement {
static get template() {
return html`
<style>
/* local styles go here */
:host {
display: inline-block;
}
iron-icon {
fill: rgba(0,0,0,0);
stroke: currentcolor;
}
:host([pressed]) iron-icon {
fill: currentcolor;
}
</style>
<!-- local DOM goes here -->
<iron-icon icon="polymer">
</iron-icon>
`;
}
}
window.customElements.define('icon-toggle', IconToggle);
デモページをリロードしてください。ハードコーディングしたアイコン表示のトグルボタンが表示されるはずです。
1つのトグルだけが押されたようなスタイルになっています。そのタグにはpressed
属性が設定されているためです。しかし、トグルボタンをクリックしても、まだトグルは動きません。pressed
プロパティを変更するコードがまだないためです。
今のところエレメントは、変化しません。このステップでは、アイコンをマークアップ上から指定するための属性の使い方と、JavaScriptからプロパティを使う方法について、基本的なAPIを紹介します。
まず、データバインディングから始めましょう。 <iron-icon>
エレメントを探して、icon
属性の値を"polymer"
から"[[toggleIcon]]
"に変更してみましょう。
<!-- local DOM goes here -->
<iron-icon icon="[[toggleIcon]]">
</iron-icon>
キーポイント:
toggleIcon
は、後でトグルボタンエレメントのプロパティとして定義します。デフォルト値はまだありません。icon="[[toggleIcon]]"
と記述することでデータバインディングを利用できます。トグルボタンエレメントのtoggleIcon
プロパティの値を<iron-icon>
のicon
プロパティにリンクします。以下の例のように、エレメントのマークアップで記述するか、JavaScriptを使用してtoggleIcon
プロパティの値を設定できます(このコードをプロジェクトに追加する必要はありません)。
<icon-toggle toggle-icon="favorite"></icon-toggle>
var myToggle = document.querySelector('icon-toggle');
myToggle.toggleIcon = "favorite";
続いて、toggleIcon
プロパティの宣言を追加します。
次のようなstatic get properties
関数をIconToggleクラスに追加してください:
class IconToggle extends PolymerElement {
static get properties() {
return {
toggleIcon: String,
};
}
キーポイント:
static get properties
関数をエレメントクラスに追加します。この関数は、プロパティ宣言を含むオブジェクトを返す必要があります。String
)だけを指定します。properties
オブジェクトは、さらにいくつかの機能をサポートしています。pressed
プロパティを利用できるようにするため、以下のように変更します。
static get properties() {
return {
toggleIcon: String,
pressed: {
type: Boolean,
value: false,
notify: true,
reflectToAttribute: true
}
};
}
キーポイント:
value
にはデフォルト値を指定します。notify
をtrue
に設定すると、値が変わったときにプロパティ変更イベントが生成されます。これにより、他のノードが変更を知ることができますreflectToAttribute
をtrue
に設定すると、プロパティ値が変更されたとき属性の値が追従します。これにより、icon-toggle[pressed]
のような属性セレクタを使用して要素にスタイルを適用できます。この修正でエレメントの pressed
と toggleIcon
プロパティが動くようになりました。
デモページをリロードすると、前のステップまでハードコーディングされていたアイコンが、星とハートのアイコンに変わって表示されているはずです。
星とハートがどこで指定されたのか興味があれば、demo/icon-toggle-demo.js
を見てください。以下のように記述されています。
<icon-toggle toggle-icon="star"></icon-toggle>
<icon-toggle toggle-icon="star" pressed></icon-toggle>
もちろん、クリックできないボタンはボタンではありません。ボタンをトグルするには、イベントリスナーを追加します。ホストエレメント(この場合はicon-toggle
)にイベントリスナーを追加するには、以下のようにGestureEventListeners
ミックスインを要素に追加します。
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import * as Gestures from '@polymer/polymer/lib/utils/gestures.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icon/iron-icon.js';
/**
* `icon-toggle`
* Get started creating custom elements with Polymer 3
*
* @customElement
* @polymer
* @demo demo/index.html
*/
class IconToggle extends GestureEventListeners(PolymerElement) {
constructor() {
super();
Gestures.addListener(this, 'tap', this.toggle.bind(this));
}
toggle() {
this.pressed = !this.pressed;
}
static get properties() {
キーポイント:
GestureEventListeners
を利用すると、ジェスチャーイベントを取得できるようになります。tap
イベントは、ユーザがマウスまたは指でターゲットをクリックまたはタップすると、Polymerのgesture systemによって生成されます。gestures
モジュール(@polymer/polymer/lib/utils/gestures.js
)のaddListener
/removeListener
メソッドを使用します。addListener
関数を使用して、ホストエレメントにリスナーを追加できます。icon-toggle.js
ファイルを保存し、デモをリロードします。ボタンを押すと、押した状態と押していない状態を切り替えることができるはずです。
これまで、ベーシックな機能のボタンを作りました。しかし、押された状態と押されていない状態の両方ともに、標準テキストカラーを使用しています。ちょっと派手にしたいと思ったら、どうしたら良いでしょう?
Shadow DOMは、ユーザーが意図せずにエレメントの内部にスタイルを適用するのを防ぎます(同時に外部からスタイルを指定できなくなります)。こうしたときのために、カスタムプロパティを使うと、エレメント内のスタイルをユーザーが設定できるように特定のプロパティセットを提供できます。
var
関数を使って、エレメント内部にカスタムプロパティを適用します。
background-color: var(--my-custom-property, defaultValue);
--my-custom-propertyはカスタムプロパティ名で、常に2つのダッシュ(--
)で始まり、defaultValueはカスタムプロパティが設定されていない場合に使用される(オプションの)CSS値です。
エレメントの<style>
タグを編集し、現在のfill
とstroke
の値をカスタムプロパティに変更します。
<style>
/* local styles go here */
:host {
display: inline-block;
}
iron-icon {
fill: var(--icon-toggle-color, rgba(0,0,0,0));
stroke: var(--icon-toggle-outline-color, currentcolor);
}
:host([pressed]) iron-icon {
fill: var(--icon-toggle-pressed-color, currentcolor);
}
</style>
SVGのデフォルト値として、color
を設定するだけで<icon-toggle>
のスタイルを変更することもできますが、他のオプションを使ってみます。 demo/icon-toggle-demo.js
を開き、以下のようにカスタムプロパティを設定します
<style>
:host {
font-family: sans-serif;
--icon-toggle-color: lightgrey;
--icon-toggle-outline-color: black;
--icon-toggle-pressed-color: red;
};
</style>
デモページをリロードするとカラフルになっているはずです。
これでチュートリアルは終わりです。基本的なUIやAPIとカスタムスタイリングプロパティを持つ要素を作成しました。
もし作業に問題があったときは、完成版のコードを参照してください。