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çãoxey, largura (width) e altura (height) e possivelmenterxerypara 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
calce atribuindo-a como o valormin-heightde 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 ids de assentos selecionados em uma variável usando amp-state e adotando uma das duas estratégias abaixo:
- Acrescentando uma expressão
amp-bindem cada assento, para adicionar o assento selecionado a uma lista - Ou usando
amp-selectorcom 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>