A radar chart (also known as spider or web chart) displays multivariate data on axes starting from a common center point, with values connected to form a polygon. Each axis represents a different variable, making it ideal for comparing multiple quantitative variables at once or visualizing strengths and weaknesses across categories.

// anyplot.ai
// radar-basic: Basic Radar Chart
// Library: muix 7.29.1 | JavaScript 22.23.1
// Quality: 89/100 | Created: 2026-07-24
//# anyplot-orientation: square
// anyplot.ai
// radar-basic: Basic Radar Chart
// Library: MUI X Charts | React | Node 22
// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.
// Quality: pending | Created: 2026-07-24
import { ChartContainer } from "@mui/x-charts/ChartContainer";
import { useDrawingArea } from "@mui/x-charts/hooks";
// @mui/x-charts 7.x community has no RadarChart component (added in v8), so the
// radar is composed on MUI X's own charting surface: ChartContainer provides the
// sized <svg> + drawing area, and useDrawingArea() gives the plot rect we map the
// polar geometry onto. Everything is real data drawn to scale — no faked chrome.
const t = window.ANYPLOT_TOKENS;
const size = window.ANYPLOT_SIZE;
// Theme-adaptive chrome (ThemeProvider handles MUI text; these are for our SVG).
const INK = t.ink;
const INK_SOFT = t.inkSoft;
const GRID = t.grid;
const PAGE_BG = t.pageBg;
// --- Data (in-memory, deterministic) — basketball player scouting report ------
const axes = ["Speed", "Shooting", "Passing", "Defense", "Rebounding", "Stamina"];
const series = [
{ label: "Guard", color: t.palette[0], values: [90, 84, 92, 68, 52, 86] },
{ label: "Forward", color: t.palette[1], values: [70, 76, 62, 85, 90, 80] },
];
const MAX = 100;
const RINGS = [20, 40, 60, 80, 100];
const N = axes.length;
// Axis i points from the top (-90°) going clockwise; SVG y grows downward.
const angleOf = (i) => (-90 + (i * 360) / N) * (Math.PI / 180);
// --- Radar layer: rendered as children inside MUI X's ChartsSurface -----------
function RadarLayer() {
const area = useDrawingArea();
const cx = area.left + area.width / 2;
const cy = area.top + area.height / 2;
const half = Math.min(area.width, area.height) / 2;
const R = half - 54; // data radius; the margin between R and half holds labels
const labelR = half - 4;
const point = (frac, i) => {
const a = angleOf(i);
return [cx + frac * R * Math.cos(a), cy + frac * R * Math.sin(a)];
};
const polygon = (frac) =>
axes.map((_, i) => point(frac, i).join(",")).join(" ");
return (
<g>
{/* Concentric grid rings at each value level — outer ring solid, inner
rings lighter/thinner so the nested grid stays subtle at the center */}
{RINGS.map((level) => (
<polygon
key={`ring-${level}`}
points={polygon(level / MAX)}
fill="none"
stroke={GRID}
strokeWidth={level === MAX ? 2 : 1}
strokeOpacity={level === MAX ? 1 : 0.6}
/>
))}
{/* Radial spokes + outer axis labels */}
{axes.map((label, i) => {
const [ox, oy] = point(1, i);
const a = angleOf(i);
const lx = cx + labelR * Math.cos(a);
const ly = cy + labelR * Math.sin(a);
const cos = Math.cos(a);
const anchor = cos > 0.15 ? "start" : cos < -0.15 ? "end" : "middle";
const sin = Math.sin(a);
const baseline = sin > 0.5 ? "hanging" : sin < -0.5 ? "auto" : "central";
return (
<g key={`axis-${label}`}>
<line x1={cx} y1={cy} x2={ox} y2={oy} stroke={GRID} strokeWidth={1.25} />
<text
x={lx}
y={ly}
fill={INK}
fontSize={18}
fontWeight={600}
textAnchor={anchor}
dominantBaseline={baseline}
>
{label}
</text>
</g>
);
})}
{/* Value tick labels, offset off the top spoke so they read on their own */}
{RINGS.map((level) => (
<text
key={`tick-${level}`}
x={cx + 12}
y={cy - (level / MAX) * R}
fill={INK_SOFT}
fontSize={15}
textAnchor="start"
dominantBaseline="central"
>
{level}
</text>
))}
{/* Series polygons: translucent fill + solid outline + vertex markers */}
{series.map((s) => (
<g key={`series-${s.label}`}>
<polygon
points={axes.map((_, i) => point(s.values[i] / MAX, i).join(",")).join(" ")}
fill={s.color}
fillOpacity={0.25}
stroke={s.color}
strokeWidth={3}
strokeLinejoin="round"
/>
{axes.map((_, i) => {
const [px, py] = point(s.values[i] / MAX, i);
return (
<circle
key={`pt-${s.label}-${i}`}
cx={px}
cy={py}
r={6}
fill={s.color}
stroke={PAGE_BG}
strokeWidth={2}
/>
);
})}
</g>
))}
</g>
);
}
// --- Title + legend drawn on the surface, then the radar layer ----------------
function Chrome() {
const legendGap = 240;
const legendStart = size.width / 2 - ((series.length - 1) * legendGap) / 2;
const legendY = size.height - 44;
return (
<g>
<text
x={size.width / 2}
y={52}
fill={INK}
fontSize={28}
fontWeight={700}
textAnchor="middle"
>
radar-basic · javascript · muix · anyplot.ai
</text>
{series.map((s, i) => {
const x = legendStart + i * legendGap;
return (
<g key={`legend-${s.label}`}>
<rect x={x - 84} y={legendY - 13} width={26} height={26} rx={5} fill={s.color} />
<text
x={x - 50}
y={legendY}
fill={INK}
fontSize={17}
textAnchor="start"
dominantBaseline="central"
>
{s.label}
</text>
</g>
);
})}
</g>
);
}
// --- Chart (default-exported component — the harness mounts it) ----------------
export default function Chart() {
return (
<ChartContainer
width={size.width}
height={size.height}
series={[]}
margin={{ top: 84, bottom: 84, left: 96, right: 96 }}
skipAnimation
>
<Chrome />
<RadarLayer />
</ChartContainer>
);
}
Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/radar-basic/muix/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.
{
"spec_id": "radar-basic",
"language": "javascript",
"library": "muix",
"page": "https://anyplot.ai/radar-basic/javascript/muix",
"hub": "https://anyplot.ai/radar-basic",
"code_json": "https://api.anyplot.ai/specs/radar-basic/muix/code",
"spec_json": "https://api.anyplot.ai/specs/radar-basic",
"render_light_png": "https://storage.googleapis.com/anyplot-images/plots/radar-basic/javascript/muix/plot-light.png",
"render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/radar-basic/javascript/muix/plot-dark.png",
"interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/radar-basic/javascript/muix/plot-light.html",
"interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/radar-basic/javascript/muix/plot-dark.html",
"quality_score": 89.0,
"license": "MIT",
"guide": "https://anyplot.ai/llms.txt"
}Part of Basic Radar Chart on anyplot.ai.