Skip to content

About

Typescript base multi-block supporting open source seat map / selection framework

Topics

Resources

Security policy

Stars

162 stars

Watchers

17 watching

Forks

Latest commit

ย 

History

553 Commits

Folders and files

Repository files navigation

Seatmap Canvas

Canvas v1 is no longer developed. It remains MIT-licensed and available on npm as @alisaitteke/seatmap-canvas. Documentation stays at the same URLs.

The maintained commercial platform (WebGL2 renderer, editor, and booking) is at seatmap.io.

Seatmap Canvas is an advanced, open-source library for interactive seat selection in various settings such as stadiums, theaters, and event spaces. Designed with d3.js, this code version is optimized for developers looking for a customizable and efficient solution to handle seat arrangements and user interactions.

LIVE DEMO

๐Ÿ“– Documentation | ๐ŸŽฏ Live Demo

Features

  • Framework Agnostic - Core library works with vanilla JS, plus official React and Vue 3 wrappers
  • Dynamic Seat Selection - Interactive selection, categorization, and location of seats
  • Custom Background Images - Global and per-block background images with positioning control
  • Customizable Styles - Extensive styling options for seats, blocks, and labels
  • Interactive Seat Models - Define properties like salability, notes, colors, and custom data
  • Block Organization - Organize seats into blocks with titles, colors, and labels
  • Event System - Simplified event listeners for seat interactions

Screenshot

LIVE DEMO

๐Ÿš€ Framework Plugins & Integrations

๐ŸŒ Web Frameworks

Vue.js 3 ย ย  React ย ย  Next.js ย ย  Svelte ย ย  Angular ย ย  Nuxt ย ย  Solid.js ย ย  Astro

๐Ÿ“ฑ Mobile Frameworks

React Native ย ย  Flutter ย ย  Expo ย ย  Ionic ย ย  Capacitor ย ย  .NET MAUI


๐ŸŒ Web Framework Integrations

Framework Status Package Documentation Example
Vanilla JS โœ… Available @alisaitteke/seatmap-canvas ๐Ÿ“– Documentation ๐ŸŽฏ Example
Vue.js 3 โš ๏ธ Testing @alisaitteke/seatmap-canvas/vue ๐Ÿ“– Documentation ๐ŸŽฏ Example
React โš ๏ธ Testing @alisaitteke/seatmap-canvas/react ๐Ÿ“– Documentation ๐ŸŽฏ Example
Next.js โš ๏ธ Testing @alisaitteke/seatmap-canvas/nextjs ๐Ÿ“– Documentation ๐ŸŽฏ App Router โ€ข Pages Router
Svelte ๐Ÿ”œ Coming Soon - - -
Angular ๐Ÿ”œ Coming Soon - - -
Nuxt ๐Ÿ”œ Coming Soon - - -
Solid.js ๐Ÿ”œ Coming Soon - - -
Astro ๐Ÿ”œ Coming Soon - - -

๐Ÿ“ฑ Mobile Framework Integrations

Framework Platform Status Package Documentation Example
React Native iOS โ€ข Android ๐Ÿ”œ Coming Soon - - -
Flutter iOS โ€ข Android ๐Ÿ”œ Coming Soon - - -
Expo iOS โ€ข Android ๐Ÿ”œ Coming Soon - - -
Ionic iOS โ€ข Android โ€ข Web ๐Ÿ”œ Coming Soon - - -
Capacitor iOS โ€ข Android โ€ข Web ๐Ÿ”œ Coming Soon - - -
.NET MAUI iOS โ€ข Android โ€ข Windows โ€ข macOS ๐Ÿ”œ Coming Soon - - -

LIVE DEMO

What does it do?

In any organization

  • Seat selection
  • Seat categorizing
  • Locating
  • Turnstile and Gate information

Installation

npm install @alisaitteke/seatmap-canvas

Quick Start


Vue.js ย Vue.js 3

Installation

npm install @alisaitteke/seatmap-canvas

Setup (main.ts)

import { createApp } from 'vue';
import App from './App.vue';
import SeatmapCanvasPlugin from '@alisaitteke/seatmap-canvas/vue';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

const app = createApp(App);
app.use(SeatmapCanvasPlugin);
app.mount('#app');

Component Usage

<template>
  <SeatmapCanvas
    :options="seatmapOptions"
    :data="blocks"
    @seat-click="onSeatClick"
  />
</template>

<script setup lang="ts">
const seatmapOptions = {
  legend: true,
  style: {
    seat: {
      hover: '#8fe100',
      selected: '#8fe100',
    }
  }
};

const onSeatClick = (seat) => {
  seat.isSelected() ? seat.unSelect() : seat.select();
};
</script>

Documentation ย  Examples


React ย React

Installation

npm install @alisaitteke/seatmap-canvas

Component Usage

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/react';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

function App() {
  const handleSeatClick = (seat) => {
    seat.isSelected() ? seat.unSelect() : seat.select();
  };

  return (
    <SeatmapCanvas
      options={{
        legend: true,
        style: {
          seat: { hover: '#8fe100', selected: '#8fe100' }
        }
      }}
      data={blocks}
      onSeatClick={handleSeatClick}
    />
  );
}

Documentation ย  Examples


Next.js ย Next.js

Installation

npm install @alisaitteke/seatmap-canvas next react react-dom

App Router (Client Component)

'use client';

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

export default function VenuePage() {
  const handleSeatClick = (seat) => {
    seat.isSelected() ? seat.unSelect() : seat.select();
  };

  return (
    <SeatmapCanvas
      data={blocks}
      options={{ legend: true }}
      onSeatClick={handleSeatClick}
    />
  );
}

Server Component + Data Fetching

import { SeatmapServerWrapper } from '@alisaitteke/seatmap-canvas/nextjs/app-router';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

export default async function VenuePage({ params }) {
  return (
    <SeatmapServerWrapper
      dataSource={`/api/venues/${params.id}/seatmap`}
      options={{ legend: true }}
      revalidate={3600}
    />
  );
}

Pages Router (Dynamic Import)

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs/pages-router';

export default function VenuePage({ data }) {
  return <SeatmapCanvas data={data} />;
}

Documentation ย  App Router ย  Pages Router


JavaScript ย Vanilla JavaScript

Quick Setup

const config = {
  resizable: true,
  seat_style: {
    radius: 12,
    color: "#6796ff",
    hover: "#5671ff",
    selected: "#56aa45"
  }
};

const seatmap = new SeatmapCanvas(".container", config);
seatmap.setData(data);

Event Handling

seatmap.addEventListener("seat_click", (seat) => {
  if (seat.selected) {
    seatmap.seatUnselect(seat);
  } else {
    seatmap.seatSelect(seat);
  }
});

// Get selected seats
const selected = seatmap.getSelectedSeats();
๐Ÿ“‹ Data Models Reference

Seat Model

{
  "id": 1,
  "title": "49",
  "x": 0,
  "y": 0,
  "salable": true,
  "note": "note test",
  "color":"#ffffff",
  "custom_data": {
    "any": "things"
  }
}

Block Model

{
  "blocks": [{
    "id": 1,
    "title": "Test Block 1",
    "color": "#2c2828",
    "labels": [{ "title": "A", "x": -30, "y": 0 }],
    "seats": [
      { "id": 1, "x": 0, "y": 0, "salable": true, "title": "49" },
      { "id": 2, "x": 30, "y": 0, "salable": true, "title": "47" }
    ]
  }]
}

Configuration Options

{
  click_enable_sold_seats: true,  // Enable clicking on unavailable seats (default: false)
  
  // Global Background Image
  background_image: "assets/stadium.jpg",      // Image URL (PNG, JPG, SVG, WebP, GIF)
  background_opacity: 0.3,                     // 0-1 (default: 0.3)
  background_fit: "cover",                     // "cover" | "contain" | "fill" | "none"
  background_x: 0,                            // Manual X position (optional, auto-detect if null)
  background_y: 0,                            // Manual Y position (optional)
  background_width: 1500,                     // Manual width (optional)
  background_height: 1000                     // Manual height (optional)
}
๐Ÿ–ผ๏ธ Custom Background Images

Global Background

Add a background image to the entire stage:

const seatmap = new SeatmapCanvas(".container", {
  background_image: "assets/concert-hall.jpg",
  background_opacity: 0.3,
  background_fit: "cover"
});

With Manual Positioning:

const seatmap = new SeatmapCanvas(".container", {
  background_image: "assets/stadium.jpg",
  background_x: -500,        // Position X
  background_y: -500,        // Position Y
  background_width: 3000,    // Width
  background_height: 2500,   // Height
  background_opacity: 0.4,
  background_fit: "contain"  // Preserve aspect ratio
});

Block-Level Background

Add custom backgrounds to individual blocks:

{
  blocks: [{
    id: "vip-section",
    title: "VIP Area",
    background_image: "assets/vip-lounge.jpg",
    background_opacity: 0.6,
    background_fit: "cover",
    seats: [...]
  }, {
    id: "general",
    title: "General Admission",
    background_image: "assets/general-area.jpg",
    background_opacity: 0.5,
    seats: [...]
  }]
}

With Manual Positioning:

{
  blocks: [{
    id: "block-a",
    background_image: "section-a.jpg",
    background_x: 100,         // Exact X coordinate
    background_y: 200,         // Exact Y coordinate
    background_width: 500,     // Exact width
    background_height: 400,    // Exact height
    background_opacity: 0.7,
    background_fit: "cover",
    seats: [...]
  }]
}

Fit Modes

  • cover (default) - Image covers entire area, may crop
  • contain - Image fits inside area, preserves aspect ratio
  • fill - Image stretches to fill area
  • none - Image keeps original size, centered

Features

  • โœ… Auto-Detection: X, Y, Width, Height auto-calculated from bounds if not specified
  • โœ… Clip-Path Masking: Block backgrounds clipped to exact block shape
  • โœ… Opacity Control: Adjustable transparency (0-1)
  • โœ… Auto-Hide Bounds: Block borders/fills hidden when background exists
  • โœ… Zoom Preserved: Bounds calculations still work for zoom levels
  • โœ… Format Support: PNG, JPG, SVG, WebP, GIF, all web-compatible formats
  • โœ… Performance: Browser-native image loading and caching

Use Cases

Stadium/Arena:

// Stadium overview as background
background_image: "stadium-aerial.jpg"

Theater:

// Stage photo per seating section
blocks: [
  { id: "orchestra", background_image: "orchestra-view.jpg" },
  { id: "balcony", background_image: "balcony-view.jpg" }
]

Restaurant:

// Floor plan as background
background_image: "floor-plan.png",
background_opacity: 0.5,
background_fit: "contain"

Event Space:

// Custom venue layout
background_image: "venue-layout.svg",
background_fit: "contain"

Important Notes

  • Background images don't affect zoom calculations (bounds preserved)
  • Block borders/fills automatically hidden when background assigned
  • CORS: Images must be same-origin or CORS-enabled
  • Performance: Use optimized images (< 500KB recommended)

Documentation ย  Examples


Links

Author

Ali Sait Teke

Ali Sait Teke

GitHub ย  LinkedIn ย  Twitter

Contributors

Contributions are welcome! Feel free to submit issues and pull requests.

About

Typescript base multi-block supporting open source seat map / selection framework

Topics

Resources

Security policy

Stars

162 stars

Watchers

17 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages