Una característica muy interesante en Angular es que a partir de su versión 8 tiene la capacidad de usar archivos SVG como plantilla en sus aplicaciones, pero ¿para qué nos sirve esto?. Cuando se usa un SVG como plantilla, puedes utilizar directivas y enlaces como con las plantillas HTML. Con estas características, puede generar gráficos interactivos de forma dinámica.
Veamos que se quiere
Compra de butacas
En una aplicación de compra de tickets para el cine es necesario visualizar las butacas que se encuentran disponibles y no disponibles, además de poder seleccionar la que deseamos comprar, esta funcionalidad la podemos realizar en Angular, construyendo un mapa interactivo utilizando SVG.
El resultado que buscamos es algo parecido a esto:

P1. Crear una imagen vectorial
Hay muchas herramientas para trabajar con imágenes vectoriales, en este caso, utilice Illustrator para crear una imagen vectorial de la sala de cine con todas sus butacas, cada una dibujada de manera individual.
P2. Exportar a SVG
La importancia de que cada dibujo este independiente es para obtener un path para cada segmento de nuestra sala, y se pueda colorear cada pieza según sea necesario.

P3. Crear proyecto en Angular
Lo primero que necesitamos es crear un proyecto en Angular, podemos utilizar de manera local comandos de Angular Cli para agilizar el proceso, o trabajar en línea con stackblitz
<!-- Crear proyecto -->
> ng new angular-svg-cinema
<!-- Archivos-->
|-- app
|-- app.component.css
|-- app.component.html
|-- app.component.ts
|-- app.module.ts
|-- data.ts
|-- enum.ts
P4. Preparar la data
Con los códigos del archivo SVG generado, se creó un objeto adicionando lo necesario para manejar las propiedades de cada segmento como color, estado, nombre o código de la butaca.
Esta data podría estar de manera externa en una tabla de base de datos.
/* data.ts */
export let DATA = [
{
code: "A1",
path:
"M133.51,102.97c-1.56,0-2.83,1.28-2.83,2.83v3.59c-1.24-3.16-4.32-5.42-7.91-5.42h-8.5 c-3.59,0-6.67,2.26-7.91,5.42v-3.59c0-1.56-1.28-2.83-2.83-2.83s-2.83,1.28-2.83,2.83v17.01c0,1.57,1.27,2.83,2.83,2.83 c0.92,0,1.72-0.45,2.24-1.13v4.96c0,1.56,1.28,2.83,2.83,2.83h19.84c1.56,0,2.83-1.28,2.83-2.83v-4.96 c0.52,0.68,1.33,1.12,2.24,1.12c1.56,0,2.83-1.28,2.83-2.83V105.8C136.35,104.25,135.07,102.97,133.51,102.97z",
color: "#CAC8C9",
status: "Disponible"
},
{
code: "A2",
path:
"M169.88,102.97c-1.56,0-2.83,1.28-2.83,2.83v3.59c-1.24-3.16-4.32-5.42-7.91-5.42h-8.5 c-3.59,0-6.67,2.26-7.91,5.42v-3.59c0-1.56-1.28-2.83-2.83-2.83s-2.83,1.28-2.83,2.83v17.01c0,1.57,1.27,2.83,2.83,2.83 c0.92,0,1.72-0.45,2.24-1.13v4.96c0,1.56,1.28,2.83,2.83,2.83h19.84c1.56,0,2.83-1.28,2.83-2.83v-4.96 c0.52,0.68,1.33,1.12,2.24,1.12c1.56,0,2.83-1.28,2.83-2.83V105.8C172.71,104.25,171.44,102.97,169.88,102.97z",
color: "#CAC8C9",
status: "Disponible"
},
/* ... */
];
P5. Vincular con el componente
En el componente principal, sin entrar en lógica de negocio, lo que tenemos que hacer es vincular cada segmento para que obtenga el color y estado apropiado, utilizando los atributos de SVG como fill y stroke.
De igual manera podemos utilizar las directivas de angular como ngFor, ngStyle o ngClass.
<!-- app.component.html -->
<div class="content">
<h1> Selección de butacas </h1>
<hr>
<svg id="mapsvg" class="map" stroke="transparent" fill-opacity="1">
<svg:path *ngFor="let item of data; let i = index"
[attr.data-index]="i"
id="item.code{{i}}"
[attr.d]="item.path"
[ngStyle]="{ fill : item.color }"
[ngClass]="'menu-cursor-pointer'"
(click)="reserve(i)">
<title>{{item.code}}</title>
</svg:path>
</svg>
</div>
En app.component.ts, cargamos la DATA al iniciar el componente, además agregamos el método reserve(), que se ejecutará cuando el usuario haga click sobre una de las butacas.
Este método cambia el color del segmento y asigna es estado Seleccionado.
/* app.component.ts */
import { Component } from "@angular/core";
import { DATA } from "./data";
import { EnumColor, EnumStatus } from "./enum";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
data = [];
ngOnInit() {
this.data = DATA;
}
reserve(i: number) {
if (this.data[i].code && this.data[i].color == EnumColor.DISPONIBLE) {
this.data[i].color = EnumColor.SELECCIONADO;
this.data[i].status = EnumStatus.SELECCIONADO;
}
}
}
También se creó un enumerado para los estados y colores.
/* enum.ts */
export enum EnumColor {
DISPONIBLE = "#CAC8C9",
OCUPADO = "#FFD348",
SELECCIONADO = "#0DA037"
}
export enum EnumStatus {
DISPONIBLE = "Dsiponible",
OCUPADO = "Ocupado",
SELECCIONADO = "Tu selección"
}
Se realizaron algunos ajustes de estilo
/* app.component.css */
.content {
max-width: 700px;
margin: auto;
}
.map {
min-height: 100vh;
width: 100%;
}
svg {
overflow: hidden;
vertical-align: middle;
}
¡Esto es todo! ¿Tenías idea de las cosas geniales que puedes construir con SVG y Angular? ¡Te leo en los comentarios!
Descargar en GitHub o stackblitz.
Excelente contenido, auxilia para proyectos de la universidad. Gracias 😀
Que bueno que te sea útil! 🙂
Thx