Skip to content
Extensões

Circular Diagram

Diagrama radial SVG com segmentos coloridos por categoria. Suporta variacoes em donut e pie, com legendas interativas e tooltips.

Uso

html
<div class="circular-diagram">
  <h3 class="circular-diagram__title">Distribuicao por Categoria</h3>
  <div class="circular-diagram__svg-wrapper">
    <svg class="circular-diagram__svg" viewBox="0 0 200 200">
      <path class="circular-diagram__segment" d="M100,10 A90,90 0 0,1 190,100" fill="#4caf50" />
      <path class="circular-diagram__segment" d="M190,100 A90,90 0 0,1 100,190" fill="#2196f3" />
      <path class="circular-diagram__segment" d="M100,190 A90,90 0 0,1 10,100" fill="#ff9800" />
      <path class="circular-diagram__segment" d="M10,100 A90,90 0 0,1 100,10" fill="#f44336" />
    </svg>
  </div>
  <div class="circular-diagram__legend">
    <div class="circular-diagram__legend-item">
      <span class="circular-diagram__legend-dot" style="background: #4caf50"></span>
      <span class="circular-diagram__legend-label">Concluido</span>
      <span class="circular-diagram__legend-value">42%</span>
    </div>
  </div>
</div>

Exemplos

Carregando exemplo...

Anatomia

ClasseElementoDescricao
.circular-diagramdivContainer principal do componente
__titleh3Titulo descritivo do diagrama
__svg-wrapperdivWrapper que centraliza e dimensiona o SVG
__svgsvgElemento SVG raiz com viewBox
__segmentpathArco representando uma categoria
__labeltextRotulo posicionado sobre ou proximo ao segmento
__valuetextValor numerico ou percentual no segmento
__centergGrupo SVG centralizado (visivel no modo donut)
__center-texttextTexto exibido no centro do donut (ex.: total)
__tooltipdivCaixa de tooltip com detalhes da categoria
__tooltip--visibledivVariante visivel do tooltip (hover/focus)
__legenddivContainer da legenda abaixo do diagrama
__legend-itemdivLinha individual na legenda
__legend-dotspanCirculo colorido correspondente ao segmento
__legend-labelspanNome da categoria na legenda
__legend-valuespanValor ou percentual na legenda
__emptydivMensagem exibida quando nao ha dados

SVG Internals

O diagrama utiliza funcoes auxiliares para calcular os arcos SVG:

polarToCartesian

Converte coordenadas polares (angulo + raio) em coordenadas cartesianas (x, y) para posicionar pontos no SVG.

js
function polarToCartesian(cx, cy, radius, angleDeg) {
  const angleRad = (angleDeg - 90) * Math.PI / 180;
  return {
    x: cx + radius * Math.cos(angleRad),
    y: cy + radius * Math.sin(angleRad),
  };
}

describeArc

Gera o atributo d de um <path> SVG que desenha um arco entre dois angulos.

js
function describeArc(cx, cy, radius, startAngle, endAngle) {
  const start = polarToCartesian(cx, cy, radius, endAngle);
  const end = polarToCartesian(cx, cy, radius, startAngle);
  const largeArc = endAngle - startAngle <= 180 ? '0' : '1';
  return [
    'M', start.x, start.y,
    'A', radius, radius, 0, largeArc, 0, end.x, end.y,
  ].join(' ');
}

Arcos (arcs)

Cada segmento e construido percorrendo o array de dados e acumulando angulos proporcionais ao valor de cada categoria:

js
let currentAngle = 0;
const total = data.reduce((sum, d) => sum + d.valor, 0);

const arcs = data.map((d) => {
  const angle = (d.valor / total) * 360;
  const arc = describeArc(100, 100, 90, currentAngle, currentAngle + angle);
  currentAngle += angle;
  return { ...d, path: arc };
});

Donut vs Pie

O componente suporta dois modos de exibicao controlados pelo innerRadius:

ModoinnerRadiusDescricao
Pie0Grafico de pizza preenchido por completo
Donut0.6Anel com espaco vazio no centro

Modo Pie (innerRadius: 0)

html
<div class="circular-diagram" data-inner-radius="0">
  <!-- Segmentos preenchem do centro ate a borda -->
</div>

No modo pie, cada segmento e desenhado como um setor completo partindo do centro do SVG.

Modo Donut (innerRadius: 0.6)

html
<div class="circular-diagram" data-inner-radius="0.6">
  <svg class="circular-diagram__svg" viewBox="0 0 200 200">
    <!-- Segmentos formam um anel -->
    <g class="circular-diagram__center">
      <text class="circular-diagram__center-text">Total: 1.250</text>
    </g>
  </svg>
</div>

No modo donut, o innerRadius define a proporcao do raio interno em relacao ao raio externo. O valor 0.6 significa que o buraco central ocupa 60% do raio. O grupo __center e __center-text ficam visiveis para exibir informacoes resumidas.

Propriedades

PropriedadeTipoDefaultDescrição

Codigo

HTML estatico

html
<div class="circular-diagram">
  <h3 class="circular-diagram__title">Distribuicao por Tipo</h3>
  <div class="circular-diagram__svg-wrapper">
    <svg class="circular-diagram__svg" viewBox="0 0 200 200">
      <path class="circular-diagram__segment"
            d="M100,10 A90,90 0 0,1 190,100"
            fill="#4caf50"
            data-label="Concluido"
            data-value="35" />
      <path class="circular-diagram__segment"
            d="M190,100 A90,90 0 0,1 100,190"
            fill="#2196f3"
            data-label="Em andamento"
            data-value="28" />
      <path class="circular-diagram__segment"
            d="M100,190 A90,90 0 1,1 100,10"
            fill="#ff9800"
            data-label="Pendente"
            data-value="37" />
      <g class="circular-diagram__center">
        <text class="circular-diagram__center-text" x="100" y="100"
              text-anchor="middle" dominant-baseline="central">
          100
        </text>
      </g>
    </svg>
  </div>
  <div class="circular-diagram__tooltip">
    <strong>Concluido</strong>: 35 (35%)
  </div>
  <div class="circular-diagram__legend">
    <div class="circular-diagram__legend-item">
      <span class="circular-diagram__legend-dot" style="background: #4caf50"></span>
      <span class="circular-diagram__legend-label">Concluido</span>
      <span class="circular-diagram__legend-value">35</span>
    </div>
    <div class="circular-diagram__legend-item">
      <span class="circular-diagram__legend-dot" style="background: #2196f3"></span>
      <span class="circular-diagram__legend-label">Em andamento</span>
      <span class="circular-diagram__legend-value">28</span>
    </div>
    <div class="circular-diagram__legend-item">
      <span class="circular-diagram__legend-dot" style="background: #ff9800"></span>
      <span class="circular-diagram__legend-label">Pendente</span>
      <span class="circular-diagram__legend-value">37</span>
    </div>
  </div>
</div>

Com DataLoader

html
<div class="circular-diagram"
     data-source="/api/distribuicao-tipos.json"
     data-inner-radius="0.6">
  <h3 class="circular-diagram__title">Distribuicao por Tipo</h3>
  <div class="circular-diagram__svg-wrapper">
    <svg class="circular-diagram__svg" viewBox="0 0 200 200" data-bind="segments">
      <!-- Segmentos renderizados automaticamente -->
    </svg>
  </div>
  <div class="circular-diagram__legend" data-bind="legend">
    <!-- Legenda renderizada automaticamente -->
  </div>
</div>

Auto-init

html
<div class="circular-diagram" data-auto-init="circular-diagram"
     data-source="/api/distribuicao-tipos.json"
     data-inner-radius="0.6">
</div>

Com data-auto-init, o componente renderiza o SVG, segmentos, legenda e tooltips automaticamente a partir da fonte de dados.

Estado vazio

html
<div class="circular-diagram">
  <h3 class="circular-diagram__title">Distribuicao por Tipo</h3>
  <div class="circular-diagram__empty">
    Nenhum dado disponivel para exibicao.
  </div>
</div>

Fonte de Dados

O componente espera um JSON com um array de objetos contendo as seguintes propriedades:

json
[
  {
    "label": "Concluido",
    "valor": 35,
    "color": "#4caf50",
    "descricao": "Processos finalizados com parecer"
  },
  {
    "label": "Em andamento",
    "valor": 28,
    "color": "#2196f3",
    "descricao": "Processos em analise ativa"
  },
  {
    "label": "Pendente",
    "valor": 37,
    "color": "#ff9800",
    "descricao": "Processos aguardando distribuicao"
  }
]
PropriedadeTipoDescricao
labelstringNome da categoria exibido na legenda e tooltip
valornumberValor numerico que define o tamanho do segmento
colorstringCor hexadecimal do segmento e do dot da legenda
descricaostringTexto descritivo exibido no tooltip ao passar o mouse

Dark Mode

O componente responde automaticamente ao dark mode via [data-theme="dark"] ou prefers-color-scheme: dark.

  • O fundo do wrapper e da legenda adapta-se ao tema escuro.
  • As cores dos segmentos mantem saturacao adequada para contraste no fundo escuro.
  • O texto central, rotulos e valores usam cor clara (--color-text-dark).
  • O tooltip usa fundo escuro com borda sutil e sombra reduzida.
  • Os dots da legenda mantem as cores originais dos segmentos.
css
/* Exemplo de customizacao no dark mode */
[data-theme="dark"] .circular-diagram__svg-wrapper {
  background: var(--color-surface-dark);
}

[data-theme="dark"] .circular-diagram__tooltip {
  background: var(--color-surface-elevated-dark);
  color: var(--color-text-dark);
}

[data-theme="dark"] .circular-diagram__center-text {
  fill: var(--color-text-dark);
}

Design System interno do GALES