シートマップの作成
Important: this documentation is not applicable to your currently selected format email!
シートマップは、チケット発行業者のウェブアプリの重要な要素ではありますが、AMP で実装するのは至難の業です。この記事では、提供されている AMP コンポーネントを組み合わせ、AMP でシートマップを実装する方法について学習します。
必要な AMP コンポーネント
必要なコンポーネントの確認から始めましょう。
amp-pan-zoom
amp-pan-zoom
は、ダブルタップやピンチ操作によってコンテンツを拡大縮小させるためのコンポーネントです。シートマップ実装の基礎として使用します。
amp-list
amp-list
は、CORS JSON エンドポイントから動的にコンテンツをフェッチし、提供されるテンプレートを使ってレンダリングするコンポーネントです。シートマップの現在の空席状況をフェッチし、ユーザーに最新のデータを表示できるようにします。
amp-bind
amp-bind
は、ページにインタラクティビティを追加するコンポーネントです。ここでは、選択されたシート数を追跡するために必要となります。
amp-selector
amp-selector
は、オプションのメニューを提示するコントロールで、ユーザーが操作することができます。シートマップ全体をオプションのメニューとし、各シートをオプションとして考えます。CSS 表現を使用することで、シートの選択状態のスタイリングが非常に簡単になります。たとえば、以下の表現の場合、シートが選択されるとオレンジ色で塗りつぶされます。
rect[selected].seat {
fill: var(--orange-theme);
}
必要なもの
- 各シートを
rect
要素で表現する SVG としてシートマップを描画するには、各シートの情報が必要です。位置x
とy
、width
、height
のほか、矩形の角に丸みをつけるにはrx
とry
が必要となります。 - 予約するために使用できる各シートの一意の識別子。
viewbox
属性に使用するシートマップの総幅と総高さ。
シートマップの描画
シートマップは、amp-list
と amp-mustache
を使ってレンダリングされます。amp-list
呼び出しからデータを受け取ると、そのデータを使用してシートをイテレートできます。
<svg preserveAspectRatio="xMidYMin slice" viewBox="0 0 {{width}} {{height}}"> {{#seats}} <rect option="{{id}}" role="button" tabindex="0" class="seat {{unavailable}}" x="{{x}}" y="{{y}}" width="{{width}}" height="{{height}}" rx="{{rx}}" ry="{{ry}}"/> {{/seats}} </svg>
予約不可シートのスタイリング
上記の例では、{{unavailable}}
は JSON エンドポイントが返して予約不可シートのスタイリングに使用すフィールドの値です。このアプローチでは、テンプレートがページ全体の <html>
要素をラップできないため、シートが予約不可能である場合に option=""
属性を削除できません。
以下のようにタグを繰り返す方法が、別のより冗長的なアプローチとして考えられます。
{{#available }}<rect option="" role="button" tabindex="0" class="seat" x="" y="" width="" height="" rx="" ry=""/>{{/available }} {{^available}}<rect role="button" tabindex="0" class="seat unavailable" x="" y="" width="" height="" rx="" ry=""/>{{/available }}
シートマップのサイズ設定
シートマップのサイズが固定されていない限り、シートマップを含む amp-list
のサイズを設定するのは困難です。amp-list
には、固定した寸法か layout="fill"
(親コンテナの利用可能なスペースを使用する)の使用が必要となります。この問題は、以下の 2 つの方法で解決できます。
- ページのヘッダーやフッターといったほかのコンポーネントが使用するスペースがわかったら、利用できるスペースを計算します。この計算は、CSS 内で
calc
式を使用して、amp-list
の親 div のmin-height
として割り当てて行います。 - ページレイアウトの高さがわかったら、flex レイアウトを使用します。
amp-pan-zoom のスタイリング
前のセクションで説明したアプローチを使用する場合、amp-pan-zoom
には、layout="fill"
も使用する必要があります。
- svg をラッピングする div を追加する
- パディングを追加する
ラッピングする div がなく、代わりに SVG にマージンを追加すると、マージンの部分はピンチとズームの領域に追加されません。
状態の処理
ユーザーがさまざまなシートをクリックする場合、amp-state
と以下のいずれかを使って、選択されたシートの id
を変数に入れて追跡することができます。
- 各シートに
amp-bind
式を追加して、選択されたシートをリストに追加する - または、選択されたすべてのシートがリストに追加されるように、
amp-selector
とアクションon="select:AMP.setState({selectedSeats: event.selectedOptions})"
を使用する
最初のアプローチの場合は、amp-selector
を追加する必要はありませんが、シートが選択または選択解除されるたびに、それぞれの amp-bind
式が評価されることになるため、シートマップの動作が非常に遅くなる可能性があります。
2 つ目のアプローチでは、テンプレートがレンダリングする各シートに対し、amp-bind
式の重複を減らすことができます。
最終的な HTML 構造
参考までに、シートマップの最終 HTML を以下に示します。
<div class="seatmap-container"> <amp-list layout="fill" src="/json/seats.json" binding="no" items="." single-item noloading> <template type="amp-mustache"> <amp-pan-zoom layout="fill" class="seatmap"> <amp-selector multiple on="select:AMP.setState({ selectedSeats: event.selectedOptions })" layout="fill"> <div class="svg-container"> <svg preserveAspectRatio="xMidYMin slice" viewBox="0 0 {{width}} {{height}}"> {{#seats}} <rect option="{{id}}" role="button" tabindex="0" class="seat {{unavailable}}" x="{{x}}" y="{{y}}" width="{{width}}" height="{{height}}" rx="{{rx}}" ry="{{ry}}"/> {{/seats}} </svg> </div> </amp-selector> </amp-pan-zoom> </template> </amp-list> </div>