Um motor de desenho 2D ao estilo do PixiJS. Monte um grafo de cena com formas e desenhe-o por um de três motores de fundo (Canvas2D, WebGL ou WebGPU), escolhido em tempo de execução.
O motor é feito em camadas: Application (ciclo de vida e laço de desenho), abaixo o Renderer (o motor de fundo), e então um grafo de cena que vai de Container (um grupo) até Graphics (algo desenhável). Você acrescenta nós ao app.stage e o renderizador os desenha.
Só navegador. O ranuts/visual precisa de um HTMLCanvasElement de verdade e de um contexto de GPU ou de Canvas. No Node ele não roda.
Crie uma aplicação, desenhe um retângulo com preenchimento e contorno mais um círculo, e ponha o laço de desenho para rodar.
import { Application, Graphics, RENDERER_TYPE } from 'ranuts/visual';const view = document.querySelector('canvas');// Application.create é assíncrono: o motor de fundo do WebGPU inicializa o dispositivo// de forma assíncrona e isso precisa terminar antes do primeiro desenho.const app = await Application.create({ view, prefer: RENDERER_TYPE.CANVAS, // CANVAS | WEB_GL | WEB_GPU backgroundColor: '#1e1e1e',});// Um retângulo: preenchimento vermelho e contorno azul de 4px.const rect = new Graphics();rect.beginFill('#ff0000');rect.lineStyle(4, '#0000ff');rect.drawRect(20, 20, 160, 100);rect.endFill();// Um círculo.const circle = new Graphics();circle.beginFill('#00cc88', 0.8);circle.drawCircle(300, 120, 60);circle.endFill();// Acrescente os desenháveis ao stage, o ancestral de tudo o que é desenhado.app.stage.addChild(rect);app.stage.addChild(circle);// Põe o laço do requestAnimationFrame para rodar (ou chame app.render() para um quadro só).app.start();
O ponto de entrada do motor. Ele é dono do canvas, do renderizador e da raiz do grafo de cena (stage).
Prefira a fábrica assíncrona Application.create(...) ao new Application(...): o motor de fundo do WebGPU inicializa o dispositivo de forma assíncrona e isso precisa terminar antes do primeiro desenho. Canvas e WebGL resolvem na hora, então a fábrica é segura e uniforme para os três.
Um nó de agrupamento, a ideia de «grupo» do grafo de cena. Guarda filhos e o estado de transformação, mas ele mesmo não desenha nada; desenháveis como o Graphics o estendem. Acrescente um Container para montar subárvores que se movem, escalam e giram juntas.
Um desenhável que estende o Container. Defina um preenchimento, um estilo de linha ou ambos, e depois chame um método de forma. Quase todos os métodos devolvem this, então as chamadas encadeiam.
O motor de fundo é escolhido por IApplicationOptions.prefer (um RENDERER_TYPE); se for omitido, usa-se o Canvas.
O CANVAS desenha direto pela API do Canvas2D (fillRect, arc, ctx.stroke(), …).
O WEB_GL e o WEB_GPU compartilham a mesma esteira BatchRenderer: as formas são partidas em triângulos, empacotadas num único buffer de vértices intercalado e desenhadas numa chamada só.
Os três aceitam qualquer cor CSS: hexadecimal (#rgb ou #rrggbb), cores com nome, rgb() e hsl() são todas resolvidas do mesmo jeito.
A geometria do contorno muda conforme o motor de fundo, e isso é de propósito. No Canvas, as pontas e as junções de linha são desenhadas pelo ctx.stroke() nativo do navegador; no WebGL e no WebGPU, por uma triangulação própria. Os dois não coincidem pixel a pixel.