UNPKG

football-lineup-generator

Version:

A TypeScript library for generating visual football lineup diagrams from team positioning data

384 lines (297 loc) 10.4 kB
# Football Lineup Generator A TypeScript library for generating visual football (soccer) lineup diagrams from team positioning data. Create beautiful, interactive lineup visualizations that can be easily embedded in web applications. ## Features - 🏈 Generate visual football field with accurate proportions - 👥 Position players based on their assigned roles - 🎨 Customizable colors, sizes, and styling - 📱 Responsive and scalable canvas-based rendering - 🔧 TypeScript support with full type definitions - Lightweight with no external dependencies - 🏆 Support for substitutes and bench players ## Screenshots | Full Pitch | Half Pitch | Split Pitch | |:----------:|:----------:|:-----------:| | ![Full Pitch](./screenshots/full-pitch.png) | ![Half Pitch](./screenshots/half-pitch.png) | ![Split Pitch](./screenshots/split-pitch.png) | ## Development ### Getting Started 1. **Install dependencies:** ```bash npm install ``` 2. **Start development environment:** ```bash npm run dev ``` This will: - Compile TypeScript in watch mode (auto-recompiles on file changes) - Start an HTTP server on `http://localhost:3000` - Automatically open `example.html` in your browser - Enable CORS for local development 3. **Alternative commands:** ```bash npm start # Same as npm run dev npm run build # One-time TypeScript compilation npm run watch # TypeScript watch mode only npm run serve # HTTP server only ``` ### Development Workflow - Make changes to TypeScript files in the `src/` directory - Changes are automatically compiled and reflected in the browser - Open `http://localhost:3000` to see the example page - The example page loads the compiled library from `dist/index.js` ### Project Structure ``` src/ ├── functions/ # Core rendering functions ├── index.ts # Main library entry point ├── renderer.ts # Football lineup renderer class └── types.ts # TypeScript type definitions ``` ## Installation ```bash npm install football-lineup-generator ``` ## Usage ### TypeScript/ESM ```typescript import { generateLineup, FootballLineupRenderer, Team, Position, LayoutType } from 'football-lineup-generator'; ``` ### CommonJS ```js const { generateLineup, FootballLineupRenderer, Team, Position, LayoutType } = require('football-lineup-generator'); ``` ## Quick Start ```typescript import { generateLineup, Team, Position, LayoutType } from 'football-lineup-generator'; // Define your lineup data const lineupData = { homeTeam: { name: "Arsenal", players: [ { player: { id: 1, name: "Ramsdale", jerseyNumber: 1 }, team: Team.RED, position: Position.GOALKEEPER }, { player: { id: 2, name: "White", jerseyNumber: 4 }, team: Team.RED, position: Position.RIGHT_BACK }, // ... more players ] }, awayTeam: { name: "Chelsea", players: [ { player: { id: 11, name: "Kepa", jerseyNumber: 1 }, team: Team.YELLOW, position: Position.GOALKEEPER }, // ... more players ] } }; // Generate the lineup canvas (now async) const canvas = await generateLineup(lineupData, { layoutType: LayoutType.SPLIT_PITCH, backgroundImage: 'path/to/field-image.jpg' }); // Add to your DOM document.body.appendChild(canvas); ``` ## API Reference ### `generateLineup(lineupData, config?)` Creates a canvas element with a football lineup visualization. **Parameters:** - `lineupData` (LineupData): The lineup data containing both teams' player positions - `config` (LineupConfig, optional): Configuration options for the visualization **Returns:** `HTMLCanvasElement` that can be added to the DOM ### `generateLineupFromPositioning(positioningData, homeTeamName, awayTeamName, config?)` Convenience function to create a lineup from backend positioning data format. **Parameters:** - `positioningData` (Array): Array of positioning data from backend - `homeTeamName` (string): Name of the home team - `awayTeamName` (string): Name of the away team - `config` (LineupConfig, optional): Configuration options **Returns:** `HTMLCanvasElement` ## Configuration Options ```typescript interface LineupConfig { width?: number; // Canvas width (default: 800) height?: number; // Canvas height (default: 600) layoutType?: LayoutType; // Layout type (default: FULL_PITCH) showPlayerNames?: boolean; // Show player names (default: true) showJerseyNumbers?: boolean; // Show jersey numbers (default: true) fieldColor?: string; // Field background color (default: '#4CAF50') lineColor?: string; // Field line color (default: '#FFFFFF') homeTeamColor?: string; // Home team player color (default: '#FF5722') awayTeamColor?: string; // Away team player color (default: '#2196F3') fontSize?: number; // Text font size (default: 12) playerCircleSize?: number; // Player circle radius (default: 20) backgroundImage?: string | HTMLImageElement; // Custom background image } ``` ## Layout Types ```typescript enum LayoutType { FULL_PITCH = "full_pitch", // Both teams positioned across the entire pitch HALF_PITCH = "half_pitch", // Each team positioned in their respective half SPLIT_PITCH = "split_pitch" // Two separate parallel pitches side by side } ``` ## Team and Position Enums ### Team ```typescript enum Team { RED = "red", YELLOW = "yellow" } ``` ### Position ```typescript enum Position { GOALKEEPER = "goalkeeper", CENTER_BACK = "center_back", LEFT_BACK = "left_back", RIGHT_BACK = "right_back", DEFENSIVE_MIDFIELDER = "defensive_midfielder", CENTER_MIDFIELDER = "center_midfielder", ATTACKING_MIDFIELDER = "attacking_midfielder", LEFT_MIDFIELDER = "left_midfielder", RIGHT_MIDFIELDER = "right_midfielder", LEFT_WINGER = "left_winger", RIGHT_WINGER = "right_winger", CENTER_FORWARD = "center_forward", LEFT_FORWARD = "left_forward", RIGHT_FORWARD = "right_forward", SUBSTITUTE = "substitute" } ``` ## Layout Options Examples ### Full Pitch Layout (Default) Both teams positioned across the entire field with traditional mirrored positioning. ```typescript const canvas = await generateLineup(lineupData, { layoutType: LayoutType.FULL_PITCH }); ``` ### Half Pitch Layout Each team positioned only in their respective half for clearer visualization. ```typescript const canvas = await generateLineup(lineupData, { layoutType: LayoutType.HALF_PITCH }); ``` ### Split Pitch Layout Two separate parallel pitches side by side, each showing one team's formation. ```typescript const canvas = await generateLineup(lineupData, { layoutType: LayoutType.SPLIT_PITCH }); ``` ## Background Image Support Add custom field backgrounds using image URLs or loaded Image elements: ```typescript // Using image URL const canvas = await generateLineup(lineupData, { backgroundImage: 'https://example.com/field-texture.jpg' }); // Using loaded Image element const img = new Image(); img.src = 'path/to/custom-field.jpg'; img.onload = async () => { const canvas = await generateLineup(lineupData, { backgroundImage: img }); document.body.appendChild(canvas); }; ``` ## Advanced Example ```typescript import { generateLineup, Team, Position, LayoutType } from 'football-lineup-generator'; // Create a 4-3-3 formation const lineupData = { homeTeam: { name: "Manchester City", players: [ // Goalkeeper { player: { id: 1, name: "Ederson", jerseyNumber: 31 }, team: Team.RED, position: Position.GOALKEEPER }, // Defense { player: { id: 2, name: "Walker", jerseyNumber: 2 }, team: Team.RED, position: Position.RIGHT_BACK }, { player: { id: 3, name: "Dias", jerseyNumber: 3 }, team: Team.RED, position: Position.CENTER_BACK }, { player: { id: 4, name: "Stones", jerseyNumber: 5 }, team: Team.RED, position: Position.CENTER_BACK }, { player: { id: 5, name: "Cancelo", jerseyNumber: 27 }, team: Team.RED, position: Position.LEFT_BACK }, // Midfield { player: { id: 6, name: "Rodri", jerseyNumber: 16 }, team: Team.RED, position: Position.DEFENSIVE_MIDFIELDER }, { player: { id: 7, name: "De Bruyne", jerseyNumber: 17 }, team: Team.RED, position: Position.CENTER_MIDFIELDER }, { player: { id: 8, name: "Silva", jerseyNumber: 20 }, team: Team.RED, position: Position.CENTER_MIDFIELDER }, // Forward { player: { id: 9, name: "Mahrez", jerseyNumber: 26 }, team: Team.RED, position: Position.RIGHT_WINGER }, { player: { id: 10, name: "Haaland", jerseyNumber: 9 }, team: Team.RED, position: Position.CENTER_FORWARD }, { player: { id: 11, name: "Grealish", jerseyNumber: 10 }, team: Team.RED, position: Position.LEFT_WINGER }, ] }, awayTeam: { name: "Liverpool", players: [ // Add Liverpool players here... ] } }; // Custom configuration with split pitch and background image const config = { width: 1000, height: 700, layoutType: LayoutType.SPLIT_PITCH, fieldColor: '#2E7D32', homeTeamColor: '#87CEEB', awayTeamColor: '#DC143C', fontSize: 14, playerCircleSize: 25, backgroundImage: 'https://example.com/stadium-field.jpg' }; const canvas = await generateLineup(lineupData, config); document.getElementById('lineup-container').appendChild(canvas); ``` ## Backend Integration If you're using the positioning data format from your backend: ```typescript import { generateLineupFromPositioning, Team, Position } from 'football-lineup-generator'; // Backend data format const backendData = [ { match_id: 1, player_id: 1, player_name: "Lionel Messi", jersey_number: 10, team: Team.RED, position: Position.RIGHT_WINGER }, // ... more positioning data ]; const canvas = generateLineupFromPositioning( backendData, "PSG", "Barcelona" ); ``` ## Browser Compatibility This library works in all modern browsers that support HTML5 Canvas: - Chrome 4+ - Firefox 2+ - Safari 3.1+ - Edge (all versions) - Internet Explorer 9+ ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## License MIT License - see LICENSE file for details. ## Changelog ### 1.0.0 - Initial release - Basic lineup generation - Canvas-based rendering - TypeScript support - Customizable styling