Cómo crear un mapa de asientos
Los mapas de asientos son una parte importante de las aplicaciones web para emitir boletos, pero puede ser complicado implementarlos en AMP. Continúe leyendo para saber cómo implementar un mapa de asientos en AMP mediante una combinación de los componentes que están disponibles en AMP.
Componentes que son necesarios en AMP
Comencemos por revisar los componentes que se necesitan:
amp-pan-zoom
amp-pan-zoom
permite tener un enfoque panorámico y un acercamiento del contenido al tocar y presionar dos veces. Este componente sirve de base para implementar el mapa de asientos.
amp-list
amp-list
recupera el contenido de forma dinámica desde un endpoint de CORS JSON y lo renderiza mediante la plantilla que se le proporciona. Se utiliza para obtener la disponibilidad actual en los mapas de asientos y de esta forma los usuarios siempre recibirán la información más reciente.
amp-bind
amp-bind
agrega interacciones a la página. Es necesario para mantener un registro de cuántos asientos se han seleccionado.
amp-selector
amp-selector
es un control que muestra un menú de opciones y permite que el usuario elija entre ellas. Todo el mapa de asientos puede considerarse un menú de opciones en el que cada asiento representa una opción. También hace que sea mucho más sencillo diseñar el estado para los asientos que fueron seleccionados, debido a que le permite utilizar expresiones CSS. Por ejemplo, en la siguiente expresión se utiliza el color naranja para indicar que un asiento está ocupado después de que se seleccionó.
rect[selected].seat {
fill: var(--orange-theme);
}
Requisitos
- Para dibujar un mapa de asientos similar a un SVG, donde cada asiento esté representado por un elemento
rect
, necesitará la siguiente información sobre cada asiento: posición dex
yy
,ancho
yalto
y posiblementerx
yry
para completar las esquinas de los rectángulos. - Un identificador único para cada asiento, que pueda utilizarse para hacer la reservación.
- Las medidas completas de ancho y alto que tendrá el mapa de asientos para utilizarlas en el atributo
viewbox
.
Cómo dibujar el mapa de asientos
El mapa de asientos se renderiza mediante amp-list
y amp-mustache
. Después de recibir los datos provenientes de la llamada amp-list
, puede utilizar dichos datos para iterar a través de los asientos:
<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>
Cómo diseñar los asientos que no están disponibles
En el ejemplo anterior, {{unavailable}}
son valores de un campo que regresó mediante el endpoint de JSON y se utilizaron para diseñar un asiento que no está disponible. Este enfoque no le permite eliminar ciertos atributos como option=""
en caso de que un asiento no esté disponible, ya que la plantilla no puede envolver a todos los elementos de las páginas <html>
.
Como alternativa, un enfoque más detallado consiste en repetir las etiquetas de la siguiente forma:
{{#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 }}
Cómo determinar el tamaño de su mapa de asientos
Salvo que el tamaño de su mapa de asientos ya esté establecido, es difícil determinar el tamaño del amp-list
que contiene el mapa de asientos. amp-list
necesita que las dimensiones ya estén establecidas, o bien utilizar layout="fill"
(para usar el espacio que esté disponible en el depósito principal). Sin embargo, existen dos formas de solucionar este problema:
- Calcular el espacio disponible en la página considerando que se conoce el espacio utilizado por otros componentes como los encabezados y los pies de página. Este cálculo puede hacerse en CSS utilizando la expresión
calc
y asignandomin-height
desde alguna de las secciones principales deamp-list
. - Utilizar un diseño flexible cuando se conozca la altura del diseño de la página.
Estilo amp-pan-zoom
Si utiliza el enfoque que se describió en la sección anterior, amp-pan-zoom
también necesita utilizar layout="fill"
.
- Agregue una división en la envoltura para el SVG
- Agregue la propiedad padding
Si no cuenta con una división en la envoltura y en su lugar le agrega un margen al SVG, esto no hará que los márgenes formen parte del área para tocar y hacer zoom.
Cómo controlar el estado
Cuando los usuarios hacen clic en diferentes asientos, es posible hacer un seguimiento del id
de los asientos seleccionados mediante una variable utilizando amp-state
, ya sea:
- Agregando una expresión
amp-bind
para cada asiento con el fin de incluir el asiento que se seleccionó en una lista. - O usando
amp-selector
con la acciónon="select:AMP.setState({selectedSeats: event.selectedOptions})"
para que todos los asientos seleccionados se agreguen a una lista.
Aunque el primer enfoque no necesita del componente adicional amp-selector
, este puede hacer que el mapa de asientos sea muy lento porque todas las expresiones amp-bind
serán evaluadas cuando se seleccione/anule cada asiento.
Además, en el segundo enfoque también se le permitirá reducir la duplicación de la expresión amp-bind
por cada asiento que será renderizado por la plantilla.
Estructura final del HTML
Como referencia, aquí puede consultar el HTML final para el mapa de asientos:
<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>