Crie um mapa de assentos
Mapas de assentos são partes importantes de aplicativos Web para venda de ingressos, mas a implementação no AMP pode ser difícil. Continue lendo para aprender como implementar um mapa de assentos no AMP usando uma combinação de componentes AMP disponíveis.
Componentes AMP necessários
Vamos iniciar revisando os componentes necessários:
amp-pan-zoom
amp-pan-zoom
permite ampliar e mover o conteúdo com usando duplo-toque e pinça com dois dedos. Este componente serve de base para a implementação do mapa de assentos.
amp-list
amp-list
busca conteúdo dinamicamente a partir de um endpoint JSON CORS e o renderiza usando um modelo fornecido. Usado para baixar a disponibilidade atual do mapa de assentos, para que os usuários sempre tenham os dados mais recentes.
amp-bind
amp-bind
adiciona interatividade à página. É necessário nesse projeto para controlar quantos assentos foram selecionados.
amp-selector
amp-selector
representa um controle que mostra um menu de opções e permite ao usuário escolher a partir dele. Todo o mapa de assentos pode ser considerado um menu de opções em que cada assento é uma opção. Isto facilita bastante a aplicação de um estilo no estado selecionado para os assentos, permitindo que se use expressões CSS. Por exemplo, a expressão a seguir preenche um assento com uma cor laranja depois que ele é selecionado.
rect[selected].seat {
fill: var(--orange-theme);
}
Requisitos
- Para desenhar um mapa de assentos como um SVG, em que cada assento é representado por um elemento
rect
, você precisa de informações sobre cada assento: posiçãox
ey
, largura (width
) e altura (height
) e possivelmenterx
ery
para arredondar os cantos dos retângulos. - Um identificador exclusivo para cada assento que esteja disponível para reservas.
- Uma medida de toda a largura e altura do mapa de assentos para usar no atributo
viewbox
.
Desenhando o mapa de assentos
O mapa de assentos é renderizado via amp-list
e amp-mustache
. Depois de receber os dados da chamada amp-list
, você pode usar esses dados para percorrer os assentos:
<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>
Aplicando estilos em assentos indisponíveis
No exemplo acima, {{unavailable}}
é o valor de um campo retornado pelo endpoint JSON e usado para aplicar um estilo num assento indisponível. Essa solução não permite remover atributos como option=""
se um assento estiver indisponível, pois o modelo não consegue empacotar os elementos <html>
das páginas inteiras.
Uma abordagem alternativa e mais detalhada é repetir as tags da seguinte maneira:
{{#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 }}
Redimensionando o mapa de assentos
A menos que o tamanho do seu mapa de assentos seja fixo, é difícil redimensionar o amp-list
que contém o mapa de assentos. O amp-list
ou precisa de dimensões fixas ou usar layout="fill"
(para usar o espaço disponível do container pai). Há duas maneiras de solucionar esse problema:
- Calcule o espaço disponível na página depois de souber quanto espaço é usado pelos outros componentes, como cabeçalhos e rodapés. Este cálculo pode ser feito em CSS usando a expressão
calc
e atribuindo-a como o valormin-height
de um div que contém oamp-list
. - Use um layout flex quando souber a altura do layout da página.
Aplicando estilos em amp-pan-zoom
Se você estiver usando a solução descrita na seção anterior, amp-pan-zoom
também precisa usar layout="fill"
.
- Adicione uma div para conter o svg
- Add margens internas (padding)
Se você não tiver uma div externa, adicione uma margem (margin) ao SVG. Isto evitará que as margens façam parte da área de pinça e zoom.
Controlando o estado
Quando os usuários clicam em assentos diferentes, é possível acompanhar os id
s de assentos selecionados em uma variável usando amp-state
e adotando uma das duas estratégias abaixo:
- Acrescentando uma expressão
amp-bind
em cada assento, para adicionar o assento selecionado a uma lista - Ou usando
amp-selector
com a açãoon="select:AMP.setState({selectedSeats: event.selectedOptions})"
para que todos os assentos selecionados sejam adicionados a uma lista
Embora a primeira solução não exija o componente adicional amp-selector
, pode deixar o mapa de assentos muito lento, porque cada expressão amp-bind
expression será avaliada cada vez que o assento for marcado/desmarcado.
A segunda alternativa também permite reduzir a duplicação da expressão amp-bind
para cada assento que será renderizado pelo modelo.
Estrutura HTML final
Para servir de referência, eis o HTML final para o mapa de assentos:
<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>