AMP

创建座位图

重要提示:此文档不适用于您当前选择的格式广告

座位图是票务商 Web 应用程序的重要组成部分,但在 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);
}

要求

  1. 要将座位图绘制为 SVG,其中每个座位都由一个 rect 元素表示,您需要每个座位的信息:位置 xywidthheight 以及可能的 rxry 来圆角矩形的角。
  2. 每个座位的唯一标识符,可用于进行预订。
  3. 要在 viewbox 属性中使用的整个座位图的宽度和高度的测量值。

绘制座位图

座位图通过 amp-listamp-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 端点返回的字段值,用于设置不可用座位的样式。此方法不允许您在座位不可用的情况下删除像 option="" 这样的属性,因为模板无法包装整个页面的 <html> 元素。

另一种更详细的方法是重复标签,如下所示

{{#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"(以使用父容器的可用空间)。有两种方法可以解决此问题

  1. 在您知道其他组件(如页眉和页脚)使用的空间后,计算页面上的可用空间。可以通过使用 calc 表达式在 CSS 中进行此计算,并将其指定为 amp-list 的父 div 的 min-height
  2. 在知道页面布局的高度时使用弹性布局。

设置 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 表达式都会在每次座位选择/取消选择时进行评估。

第二种方法还允许您减少由模板渲染的每个座位的 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>