Skip to content

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

License

Notifications You must be signed in to change notification settings

alisaitteke/seatmap-canvas

Repository files navigation

Seatmap Canvas

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 πŸ”œ Coming Soon - - -
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


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.