@mlalbuquerque/court-canvas
v1.4.0
Published
Uma library agnóstica para renderização vetorial de prancheta tática.
Readme
Court Canvas
Uma biblioteca agnóstica, modular e focada na renderização vetorial (2D) de pranchetas táticas esportivas baseada em Konva.js.

O Court Canvas permite criar rapidamente um campo de futebol interativo onde você pode arrastar jogadores, desenhar marcações geométricas (retângulos, elipses, setas directionais) e, mais importante, serializar e extrair esse estado para JSON e Imagens (.png) para salvar tudo num banco de dados.
✨ Funcionalidades (O que o Motor Faz?)
- 🏟️ Design Preciso: Background matemático renderizando grandes e pequenas áreas perfeitamente dimensionadas.
- 🖐 Interatividade Completa (Drag & Drop): Padrão State nas ferramentas (clique e arraste jogadores para construir a tática).
- 🧱 Bounding Box Auto-Ajustável: Suas peças de xadrez não saem para fora da linha do campo; algoritmos matemáticos seguram os elementos nas bordas corretas!
- 🎨 Toolbar Inteligente: Destaque visual da ferramenta ativa e seletores automáticos de cor. Modifique a cor da equipe, estilos e passes diretamente na barra!
- 🖱️ Cursores Contextuais: O ponteiro do mouse muda conforme a ferramenta (Mão para seleção, Cruz para desenho, Mira para jogadores), tornando a experiência intuitiva.
- ⏪ Viajante do Tempo: Histórico de Estado 100% autônomo. Botões e Teclas de Atalho (
CTRL+ZeCTRL+Y) suportados para desfazer e refazer marcações. - 📸 Exportação e Importação: Salve sua tática em
JSONpara carregar num backend, ou renderize uma imagem em HQ (.png) da tática em um instante. Você também pode reimportar payloads JSON para continuar editando táticas salvas! - ✨ Popups UI Modernos: Prompts de renomeação de jogadores (
dblclick), importação de dados e caixas de ajuda alimentadas peloSweetAlert2nativamente. - ⚛️ Integração Agnóstica: Pode ser executado em Vanilla JS, ReactJS ou VueJS.
🛠 Desenvolvimento e Infraestrutura (Docker)
Para garantir que todos os desenvolvedores usem a mesma versão do Node.js (v24+) e evitar conflitos de sistema, o projeto utiliza uma infraestrutura containerizada. Você não precisa ter o Node instalado na sua máquina, apenas o Docker.
Comandos de Atalho
Use os scripts na pasta infra/ para rodar comandos NPM ou Node dentro do container:
# Instalar dependências
./infra/npm install
# Rodar o servidor de desenvolvimento
./infra/npm run dev
# Rodar qualquer comando NPX
./infra/npx vitest🚀 Instalação (Uso em Produção)
O pacote está oficialmente distribuído no NPM Registry:
npm install @mlalbuquerque/court-canvas💻 Exemplos de Uso (Demos)
1. Customização Avançada (Ícones, Emojis e Ferramentas)
Você pode estender a biblioteca com seus próprios ícones (arquivos de imagem) ou usar Emojis/Texto diretamente como avatares.
💡 Dica: A propriedade
imageUrlcarrega arquivos externos (preferencialmente SVGs), enquanto a propriedadeimageaceita strings de texto ou emojis.
import { CourtCanvas } from '@mlalbuquerque/court-canvas';
const court = new CourtCanvas('meu-campo', {
width: 800,
height: 500,
customTools: [
{
id: 'ball',
type: 'stamp',
icon: '⚽',
imageUrl: 'https://exemplo.com/bola.svg', // Carrega arquivo de imagem
label: 'Bola de Futebol'
},
{
id: 'custom-player',
type: 'player',
icon: '👤',
image: '👤', // Usa emoji diretamente como avatar do jogador
label: 'Jogador Especial',
numberPosition: 'bottom-right' // 'center' (padrão) ou 'bottom-right'
}
],
toolbar: {
// Escolha quais botões exibir e a ordem
buttons: ['select', 'player-a', 'player-b', 'custom-player', 'ball', 'arrow', 'clear']
}
});2. Jogadores e Equipes (Novo v1.4.0)
Agora você pode identificar jogadores por nome e gerenciar elencos completos.
Rótulos Editáveis
Ao dar um duplo-clique em qualquer jogador no campo, um menu abrirá para editar o Número e o Nome. O nome aparecerá centralizado logo abaixo do ícone do jogador.
Ferramenta de Elenco (Team List)
Você pode cadastrar times inteiros com fotos e metadados. Quando a ferramenta é selecionada, o banco de reservas abre para você escolher quem entra em campo.
const court = new CourtCanvas('container', {
customTools: [
{
id: 'meu-time',
type: 'team',
label: 'Meu Time',
icon: 'https://path-to-badge.png', // Escudo do time ou emoji '🛡️'
teamColor: '#3498db',
players: [
{ name: 'Jogador 1', number: 10, photo: 'https://path-to-photo.png' },
{ name: 'Jogador 2', number: 7 },
{ name: 'Jogador 3', number: 11 }
]
}
]
});3. Vanilla JavaScript (O HTML puro)
<div id="meu-campo"></div>
<script type="module">
import { CourtCanvas } from '@mlalbuquerque/court-canvas';
// Inicialização simples
const court = new CourtCanvas('meu-campo', { width: 800, height: 500 });
// Carregando um estado salvo (JSON)
const savedState = '{"className":"Layer","children":[...]}';
const courtWithState = new CourtCanvas('outro-campo', { initialState: savedState });
</script>2. React
import React, { useState } from 'react';
import CourtCanvasReact from '@mlalbuquerque/court-canvas/react';
const TacticalBoard = () => {
const [court, setCourt] = useState(null);
const handleExport = () => {
if (court) {
const data = court.jsonExporter.export();
console.log('JSON da tática:', data);
}
};
return (
<div>
<CourtCanvasReact
onCanvasReady={(instance) => setCourt(instance)}
width={800}
height={500}
/>
<button onClick={handleExport}>Exportar JSON</button>
</div>
);
};3. Vue 3 (Composition API)
<template>
<div>
<CourtCanvasVue
@ready="onReady"
:width="800"
:height="500"
/>
<button @click="handleExport">Exportar JSON</button>
</div>
</template>
<script setup>
import CourtCanvasVue from '@mlalbuquerque/court-canvas/vue';
import { ref } from 'vue';
const court = ref(null);
const onReady = (instance) => {
court.value = instance;
};
const handleExport = () => {
if (court.value) {
const data = court.value.jsonExporter.export();
console.log('JSON da tática:', data);
}
};
</script>🧪 Qualidade e Segurança
O projeto possui um fluxo rigoroso de Garantia de Qualidade (QA):
1. Testes Automatizados
- Unitários (Vitest): Focados na lógica do
StateManager,ExporterseTools. - E2E (Playwright): Validam o fluxo completo do usuário no navegador.
./infra/npm run test # Roda testes unitários
./infra/npm run test:e2e # Roda testes de ponta a ponta2. Bloqueio de Push (Husky)
Existe um "Git Hook" configurado que impede o envio de código para o servidor (git push) se os testes não estiverem passando. Isso garante que a main esteja sempre estável.
3. CI/CD (GitHub Actions)
Toda alteração enviada ao GitHub dispara automaticamente o Test Suite na nuvem para uma validação final em ambiente limpo.
🛠 Arquitetura do Pacote
src/core/: Núcleo algorítmico agnóstico focado em Konva.js.src/core/Tools/: Ferramentas de interação (PlayerTool, ArrowTool, etc).src/core/Exporters/: Formatadores de saída (JsonExportereImageExporter).src/react/esrc/vue/: Wrappers para frameworks UI modernos.
