UNPKG

football-lineup-generator

Version:

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

47 lines (46 loc) 3.37 kB
import { Position } from '../types.js'; import { drawField } from './drawField.js'; import { drawTeamLabel } from './drawTeamLabel.js'; import { calculatePlayerCoordinates } from './calculatePlayerCoordinates.js'; import { calculateLabelPositions } from './calculateLabelPositions.js'; import { drawPlayer } from './drawPlayer.js'; import { mirrorCoordinatesForAwayTeam } from './mirrorCoordinates.js'; export function renderFullPitch(ctx, lineupData, config) { // Draw field drawField(ctx, config.width, config.height, config.fieldColor, config.lineColor); // Draw team labels drawTeamLabel(ctx, lineupData.homeTeam.name, true, config.width, config.homeTeamColor, config.awayTeamColor, config.fontSize); drawTeamLabel(ctx, lineupData.awayTeam.name, false, config.width, config.homeTeamColor, config.awayTeamColor, config.fontSize); // Calculate coordinates for home team players (exclude substitutes) // Apply -20px offset to move home team left and prevent center overlap const homeFieldPlayers = lineupData.homeTeam.players.filter(p => p.position !== Position.SUBSTITUTE); const homePlayerCoords = calculatePlayerCoordinates(homeFieldPlayers, config.width, config.height, config.layoutType, 0, false, true, -20 // Move home team left by 20px ); // Calculate coordinates for away team players (exclude substitutes) // Apply -20px offset which will become +20px after mirroring, moving away team right const awayFieldPlayers = lineupData.awayTeam.players.filter(p => p.position !== Position.SUBSTITUTE); const awayPlayerCoords = calculatePlayerCoordinates(awayFieldPlayers, config.width, config.height, config.layoutType, 0, false, false, -20 // This becomes +20px after mirroring, moving away team right ); // Create mirrored coordinates for away team const awayPlayerCoordsWithMirroring = awayPlayerCoords.map(({ player, coordinates }) => ({ player, coordinates: mirrorCoordinatesForAwayTeam(coordinates, config.width) })); // Calculate smart label positions with cross-team proximity analysis const allPlayersWithCoords = [...homePlayerCoords, ...awayPlayerCoordsWithMirroring]; const playersWithLabelPositions = calculateLabelPositions(allPlayersWithCoords, allPlayersWithCoords); // Draw home team players (left side) for (const playerWithLabel of playersWithLabelPositions) { const isHomePlayer = homePlayerCoords.some(hp => hp.player === playerWithLabel.player); if (isHomePlayer) { drawPlayer(ctx, playerWithLabel.player, playerWithLabel.coordinates, true, config.homeTeamColor, config.awayTeamColor, config.playerCircleSize, config.showJerseyNumbers, config.showPlayerNames, config.fontSize, allPlayersWithCoords, playerWithLabel.shouldPlaceLabelAbove); } } // Draw away team players (right side, mirrored) for (const playerWithLabel of playersWithLabelPositions) { const isAwayPlayer = awayPlayerCoordsWithMirroring.some(ap => ap.player === playerWithLabel.player); if (isAwayPlayer) { drawPlayer(ctx, playerWithLabel.player, playerWithLabel.coordinates, false, config.homeTeamColor, config.awayTeamColor, config.playerCircleSize, config.showJerseyNumbers, config.showPlayerNames, config.fontSize, allPlayersWithCoords, playerWithLabel.shouldPlaceLabelAbove); } } }