Skip to main content
Gremorie
Data

Radar Chart

Compare séries entre múltiplos eixos que compartilham um único domínio radial.

Visão geral

RadarChart é o wrapper estilizado sobre o RadarChart do recharts, composto sobre o primitive chart do shadcn (ChartContainer). Cada linha de dados (xKey) se torna um raio no grid polar; cada entrada em config se torna um polígono fechado que compartilha um único máximo radial. Use quando você tem três a sete dimensões que devem ser avaliadas juntas - perfis de habilidade, scores de satisfação, análise de gap de capacidade.

Use RadarChart quando nenhuma dimensão única é o destaque e a forma do polígono carrega significado por todo o conjunto. Para comparar uma dimensão ordenada, LineChart lê mais rápido. Para ranquear categorias em uma única métrica, BarChart é mais legível.

A escala radial é fixa em 100 por padrão. Isso é deliberado: comparação é o trabalho usual deste chart, e uma escala derivada do dado faz alguém com nota máxima 70 preencher o gráfico igual a alguém que tirou 100. Passe um número para outro teto, ou max="auto" quando a faixa não for conhecida de antemão.

A edição React (@gremorie/rx-data) renderiza com recharts dentro do primitive chart do shadcn; a edição Angular (@gremorie/ng-data) renderiza geometria d3 headless dentro de um SVG estilizado. O motor de renderização difere; a superfície pública é idêntica input-por-input.

Anatomia

<radar-chart>
└─ figure (role="img")                  card surface, aspect-square
   ├─ svg
   │  ├─ polar grid (gridType: polygon | circle, ring count from ticks)
   │  ├─ angle axis (spokes from xKey, wrapped to labelWidth)
   │  ├─ radius axis ticks (optional via radiusAxis)
   │  ├─ radar polygons, one per config key (fill: auto | on | off)
   │  ├─ vertex dots, one per row per series (optional via dots)
   │  └─ active dot, one per series, on the hovered spoke
   ├─ tooltip overlay (optional via tooltip)
   ├─ legend (when config has >1 series)
   └─ sr-only data table

A edição React compõe esta superfície através do primitive chart do shadcn:

RadarChart
└─ ChartContainer            responsive square frame + injects --color-<key>
   └─ RadarChart (recharts)  polar plot area over the angular axis (xKey)
      ├─ ChartTooltip        hover card (ChartTooltipContent)
      ├─ PolarAngleAxis      spoke labels (xKey, wrapped to labelWidth)
      ├─ PolarRadiusAxis     the scale: max, ticks, radiusAxis
      ├─ PolarGrid           polygon or circular grid (gridType)
      └─ Radar               one polygon per series, with dot / activeDot

Preview

'use client';import {  RadarChart,  type ChartConfig,  type ChartDatum,} from '@gremorie/rx-data';const monthlyData: ChartDatum[] = [  { month: 'Jan', desktop: 186, mobile: 80 },  { month: 'Feb', desktop: 305, mobile: 200 },  { month: 'Mar', desktop: 237, mobile: 120 },  { month: 'Apr', desktop: 173, mobile: 190 },  { month: 'May', desktop: 209, mobile: 130 },  { month: 'Jun', desktop: 214, mobile: 140 },];const monthlyConfig: ChartConfig = {  desktop: { label: 'Desktop', color: 'var(--chart-1)' },  mobile: { label: 'Mobile', color: 'var(--chart-2)' },};export function RadarChartPreview() {  // These counts run to 305, past the 100 the scale is pinned at by default.  // `auto` is the right answer for a range like this one, which has no natural  // ceiling — a hardcoded top would need revisiting every time the data moves.  return (    <RadarChart      data={monthlyData}      config={monthlyConfig}      xKey="month"      max="auto"    />  );}

Instalação

bash npx gremorie@latest add rx-radar-chart

bash pnpm dlx gremorie@latest add rx-radar-chart

bash yarn dlx gremorie@latest add rx-radar-chart

bash bunx --bun gremorie@latest add rx-radar-chart

Uso

import { RadarChart } from "@gremorie/rx-data";
import type { ChartConfig, ChartDatum } from "@gremorie/rx-data";

const data: ChartDatum[] = [
{ skill: "Speed", a: 90, b: 60 },
{ skill: "Power", a: 70, b: 80 },
{ skill: "Stamina", a: 85, b: 70 },
{ skill: "Agility", a: 75, b: 90 },
{ skill: "Skill", a: 95, b: 65 },
];

const config: ChartConfig = {
a: { label: "Player A", color: "var(--chart-1)" },
b: { label: "Player B", color: "var(--chart-2)" },
};

export function PlayerComparison() {
  return <RadarChart data={data} config={config} xKey="skill" />;
}
npx gremorie@latest add ng-radar-chart

Pré-requisito

Os componentes Angular emitem classes utilitárias do Tailwind e não embarcam CSS compilado. Sem o setup abaixo em src/styles.css, o componente monta mas renderiza sem estilo nenhum. Requer Tailwind CSS v4.

@import 'tailwindcss';@import '@gremorie/tokens/theme.css';/* Required. Tailwind v4 skips node_modules by default, so without this line   the components' utility classes never reach your compiled CSS and every   Gremorie component renders unstyled. */@source '../node_modules/@gremorie';

A linha @source é obrigatória: o Tailwind v4 ignora node_modules por padrão. Ajuste o caminho relativo se o seu stylesheet não estiver em src/styles.css. Setup completo em Instalação.

import { Component } from '@angular/core';
import { RadarChart } from '@gremorie/ng-data';
import type { ChartConfig, ChartDatum } from '@gremorie/ng-data';

@Component({
  selector: 'app-player-comparison',
  imports: [RadarChart],
  template: `<radar-chart [data]="data" [config]="config" xKey="skill" />`,
})
export class PlayerComparisonComponent {
  readonly data: ChartDatum[] = [
    { skill: 'Speed', a: 90, b: 60 },
    { skill: 'Power', a: 70, b: 80 },
    { skill: 'Stamina', a: 85, b: 70 },
    { skill: 'Agility', a: 75, b: 90 },
    { skill: 'Skill', a: 95, b: 65 },
  ];

  readonly config: ChartConfig = {
    a: { label: 'Player A', color: 'var(--chart-1)' },
    b: { label: 'Player B', color: 'var(--chart-2)' },
  };
}

API

<RadarChart>

O wrapper estilizado sobre o RadarChart do recharts, composto sobre ChartContainer. Renderiza o frame responsivo, um PolarGrid, o PolarAngleAxis (labels dos raios), um tooltip opcional e um <Radar> por chave de config colorido com var(--color-<key>).

PropTypeDefaultDescrição
dataChartDatum[]-Dados tabulares. Uma linha por raio. Cada linha carrega o label do raio em xKey mais um valor numérico por chave de config.
configChartConfig-Mapeia cada chave de série para { label, color }. A color é qualquer cor CSS ou token, tipicamente "var(--chart-1)" até "var(--chart-5)". ChartContainer injeta cada uma como uma CSS variable var(--color-<key>).
xKeystring-Nome do campo do raio (ângulo) em cada linha. Determina os labels do PolarAngleAxis ao redor do perímetro.
gridType"polygon" | "circle""polygon"Forma dos anéis do PolarGrid - polígono de bordas retas (padrão) ou círculos concêntricos.
maxnumber | "auto"100Topo da escala radial, ou "auto" para seguir o maior valor do dado. Fixo para que dois gráficos sejam lidos na mesma régua: com escala derivada, uma nota máxima de 70 preenche o gráfico igual a uma de 100. Isso é certo para porcentagem ou nota e errado acima de 100 — passe um número para essa faixa, ou "auto" quando a faixa não for conhecida de antemão.
ticksnumber4Número de anéis da grade, e de marcas no eixo radial.
radiusAxisbooleanfalseRotula cada anel com seu valor, subindo pela vertical.
labelWidthnumber-Quebra os rótulos dos eixos nesta largura em pixels, por palavra. Sem isso, um rótulo longo na lateral do círculo é desenhado em uma linha só, atravessando metade do gráfico.
dotsbooleanfalseDesenha um ponto em cada vértice. O raio sob o mouse ganha um ponto maior de qualquer forma.
fill"auto" | "on" | "off""auto"Preenchimento do polígono. auto preenche uma série sozinha e apenas contorna duas ou mais, para que séries sobrepostas continuem legíveis.
tooltipbooleantrueAlterna o tooltip de hover.
classNamestring-Mesclado no ChartContainer. O estilo empacotado centraliza o gráfico com um aspect quadrado.

Compondo com o primitive chart

Para controle total, componha recharts diretamente dentro de ChartContainer usando os primitives exportados. Isso espelha o bloco de radar oficial do shadcn.

ExportPapel
ChartContainerFrame responsivo; injeta as vars --color-<key> por série a partir do config.
ChartTooltipReexport do Tooltip do recharts; combine com ChartTooltipContent.
ChartTooltipContentCorpo de tooltip estilizado.
ChartLegendReexport do Legend do recharts; combine com ChartLegendContent.
ChartLegendContentCorpo de legenda estilizado.
useChartHook para ler o config ativo dentro de um child customizado.

Types

TypeShape
ChartDatumRecord<string, string | number> & { fill?: string } - uma linha de dados do chart.
ChartConfigRecord<string, { label?: ReactNode; color?: string }> - mapa de label e cor por série.
import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
  type ChartDatum,
} from '@gremorie/rx-data';
import { PolarAngleAxis, PolarGrid, Radar, RadarChart } from 'recharts';

const config = {
  a: { label: 'Player A', color: 'var(--chart-1)' },
  b: { label: 'Player B', color: 'var(--chart-2)' },
} satisfies ChartConfig;

export function Example({ data }: { data: ChartDatum[] }) {
  return (
    <ChartContainer
      config={config}
      className="mx-auto aspect-square max-h-[250px]"
    >
      <RadarChart accessibilityLayer data={data}>
        <ChartTooltip cursor={false} content={<ChartTooltipContent />} />
        <PolarAngleAxis dataKey="skill" />
        <PolarGrid gridType="polygon" />
        <Radar
          dataKey="a"
          fill="var(--color-a)"
          fillOpacity={0}
          stroke="var(--color-a)"
          strokeWidth={2}
        />
        <Radar
          dataKey="b"
          fill="var(--color-b)"
          fillOpacity={0}
          stroke="var(--color-b)"
          strokeWidth={2}
        />
      </RadarChart>
    </ChartContainer>
  );
}

Desça a este nível para traços tracejados, preenchimentos de gradiente, dots marcadores nas interseções dos raios ou uma legenda customizada via ChartLegend + ChartLegendContent.

Composição

  1. Escolha o xKey - o campo de label do raio. Três a sete raios é o ponto ideal; menos e você obtém um triângulo que esconde a forma, mais e os eixos se aglomeram.
  2. Escreva o config com no máximo três séries. Os polígonos permanecem legíveis quando traçados; quatro ou mais ficam difíceis de ler.
  3. Ordene os raios consistentemente entre gráficos na mesma superfície para que os usuários possam comparar formas por memória muscular.
  4. Escolha o gridType - polygon (padrão) segue a geometria dos raios; circle lê como um alvo/dartboard quando o alinhamento exato dos raios importa menos.
  5. Decida a escala. Deixe max em 100 para porcentagem ou nota; passe um número para um teto conhecido; use "auto" quando a faixa vier de algum lugar que você não controla. Um topo fixo não é limite suave - o que passar dele desenha fora do anel externo.
  6. Dê largura aos rótulos longos. Acima de quatro ou cinco raios, o labelWidth é o que impede uma categoria do tamanho de uma frase de atravessar o gráfico.

O chart se auto-dimensiona ao pai através do frame responsivo do ChartContainer, com um aspect quadrado para que os polígonos permaneçam simétricos.

Variações

Comparação multi-série

'use client';import {  RadarChart,  type ChartConfig,  type ChartDatum,} from '@gremorie/rx-data';const monthlyData: ChartDatum[] = [  { month: 'Jan', desktop: 186, mobile: 80 },  { month: 'Feb', desktop: 305, mobile: 200 },  { month: 'Mar', desktop: 237, mobile: 120 },  { month: 'Apr', desktop: 173, mobile: 190 },  { month: 'May', desktop: 209, mobile: 130 },  { month: 'Jun', desktop: 214, mobile: 140 },];const monthlyConfig: ChartConfig = {  desktop: { label: 'Desktop', color: 'var(--chart-1)' },  mobile: { label: 'Mobile', color: 'var(--chart-2)' },};export function RadarChartPreview() {  // These counts run to 305, past the 100 the scale is pinned at by default.  // `auto` is the right answer for a range like this one, which has no natural  // ceiling — a hardcoded top would need revisiting every time the data moves.  return (    <RadarChart      data={monthlyData}      config={monthlyConfig}      xKey="month"      max="auto"    />  );}
const config: ChartConfig = {
  a: { label: 'Player A', color: 'var(--chart-1)' },
  b: { label: 'Player B', color: 'var(--chart-2)' },
};

<RadarChart data={data} config={config} xKey="skill" />;
<radar-chart [data]="data" [config]="config" xKey="skill" />

A forma mais comum. Duas séries traçadas deixam o usuário comparar as pegadas dos polígonos num relance. Mantenha a contagem em duas ou três antes que os polígonos sobrepostos derrotem a comparação.

Perfil de série única

<RadarChart
  data={data}
  config={{ score: { label: 'Score', color: 'var(--chart-1)' } }}
  xKey="dimension"
/>
<radar-chart [data]="data" [config]="config" xKey="dimension" />

Para perfis de sujeito único - um jogador, um produto, um time. Um único polígono preenchido lê limpo mesmo com cinco ou seis raios.

Escala com nota

'use client';import {  RadarChart,  type ChartConfig,  type ChartDatum,} from '@gremorie/rx-data';// A competency review: every value is a 0-100 score, and the same nine// dimensions are rated by three different sources.const reviewData: ChartDatum[] = [  { skill: 'Discovery', self: 82, manager: 74, peers: 68 },  { skill: 'Prototyping', self: 74, manager: 66, peers: 71 },  { skill: 'Visual craft', self: 66, manager: 79, peers: 83 },  { skill: 'Product knowledge', self: 58, manager: 62, peers: 55 },  { skill: 'Problem framing', self: 77, manager: 58, peers: 64 },  { skill: 'Communication', self: 85, manager: 81, peers: 88 },  { skill: 'Collaboration', self: 69, manager: 84, peers: 79 },  { skill: 'Autonomy', self: 61, manager: 70, peers: 58 },  { skill: 'Delivery', self: 73, manager: 67, peers: 76 },];const reviewConfig: ChartConfig = {  self: { label: 'Self', color: 'var(--chart-1)' },  manager: { label: 'Manager', color: 'var(--chart-2)' },  peers: { label: 'Peers', color: 'var(--chart-3)' },};export function RadarChartScoredPreview() {  return (    <RadarChart      data={reviewData}      config={reviewConfig}      xKey="skill"      // Pinned, not derived: every review has to be read against the same      // ruler, or someone whose best score is 70 looks identical to someone      // who scored 100.      max={100}      ticks={10}      radiusAxis      // Nine spokes with two-word labels; without a width the longest is drawn      // as one run and reaches back across the plot.      labelWidth={90}      dots    />  );}

Tudo o que o chart oferece para uma leitura comparativa, numa superfície só: escala fixa em 0-100 com um anel a cada dez e cada anel rotulado, rótulos de raio quebrados para que nove caibam, e um ponto em cada vértice. É a forma que uma avaliação de competência pede - três fontes avaliando as mesmas dimensões, lidas na mesma régua.

<radar-chart
  [data]="data"
  [config]="config"
  xKey="skill"
  [max]="100"
  [ticks]="10"
  [radiusAxis]="true"
  [labelWidth]="90"
  [dots]="true"
/>

O max={100} é a prop que sustenta o resto. Sem ele a escala segue o dado, e duas avaliações deixam de ser comparáveis: quem tem nota máxima 70 preenche o gráfico igual a quem tirou 100.

Deixando o dado definir a escala

<RadarChart data={data} config={config} xKey="metric" max="auto" />
<radar-chart [data]="data" [config]="config" xKey="metric" max="auto" />

Quando a faixa não é conhecida de antemão - saída de modelo, uma API que você não controla, contagens em vez de notas - o "auto" mede contra o maior valor presente. O domínio é arredondado para um limite legível, então o polígono mais externo fica logo dentro do anel, não exatamente sobre ele.

Preenchido ou contornado

<RadarChart data={data} config={config} xKey="skill" fill="on" />
<radar-chart [data]="data" [config]="config" xKey="skill" fill="on" />

O fill é "auto" por padrão: uma série sozinha é preenchida, duas ou mais são contornadas, porque preenchimentos translúcidos empilhados embaçam rápido. Force nos dois sentidos com "on" ou "off" - forçar ligado acima de uma série clareia o preenchimento para a pilha continuar legível.

Grid de polígono

O gridType padrão. Anéis de polígono de bordas retas seguem os raios, enfatizando a geometria por raio.

<RadarChart data={data} config={config} xKey="skill" gridType="polygon" />
<radar-chart [data]="data" [config]="config" xKey="skill" gridType="polygon" />

Grid de círculo

Defina gridType como "circle" para círculos concêntricos que leem como um alvo ou dartboard, mantendo os anéis como uma escala radial neutra quando o alinhamento exato dos raios importa menos.

<RadarChart data={data} config={config} xKey="skill" gridType="circle" />
<radar-chart [data]="data" [config]="config" xKey="skill" gridType="circle" />

Acessibilidade

  • o accessibilityLayer do recharts adiciona navegação por teclado e anúncios de screen reader para as séries plotadas.
  • os tokens --chart-1 até --chart-5 vêm com contraste WCAG AA contra o fundo do card em ambos os temas claro e escuro.
  • Labels dos raios: cada tick do PolarAngleAxis é renderizado como <text> SVG ao redor do polígono, mantendo o mapeamento cor-para-série legível junto com o tooltip.
  • Limite as séries: mantenha a contagem baixa. Polígonos contornados suportam mais que preenchidos, mas acima de cinco séries a paleta categórica para de atribuir cor distinta - da sexta em diante vem um neutro apagado, em vez de repetir a primeira cor e pintar duas séries iguais.
  • Hover nunca é obrigatório para ler um valor: o tooltip lê o raio inteiro de uma vez, o alvo é a cunha toda e não o vértice, e todo valor também está na tabela sr-only.

Relacionados

  • LineChart - use uma linha quando uma dimensão ordenada é o destaque.
  • BarChart - use barras quando ranquear categorias em uma única métrica.
  • RadialChart - layout polar irmão quando as categorias devem ser mostradas como arcos concêntricos.

On this page