纯HTML无法直接绘制雷达图,必须依赖或;CSS缺乏极坐标系统,硬凑会导致误差累积、响应式错位、填充受限及事件定位不准。

纯 HTML 无法直接绘制雷达图——<canvas></canvas> 或 <svg></svg> 是必需的载体,浏览器不支持用 <div> 和 CSS transform 拼出准确的极坐标多边形。<h3>为什么不能只用 HTML + CSS 做雷达图</h3>
<p>CSS 缺乏原生极坐标系统,所有“CSS 雷达图”本质上是用 <code>transform: rotate() + position: absolute 硬凑角度和半径,导致:
• 数据点位置随角度增加累积误差(尤其 >6 个维度时)
• 无法动态计算多边形顶点坐标,缩放/响应式会错位
• 填充区域只能靠伪元素或遮罩模拟,不支持透明度叠加与交集裁剪
• 没有事件坐标映射,点击某个轴或区域无法准确定位数据维度
用
核心是把极坐标 (r, θ) 转为直角坐标 (x, y): x = centerX + r * cos(θ),y = centerY + r * sin(θ)。注意:Math.cos/Math.sin 的参数单位是弧度,不是角度。
- 先算出每个维度对应的角度步长:
angleStep = (Math.PI * 2) / data.length - 对每个数据点,用归一化后的值(如
value / maxValue)乘以最大半径,再套公式转坐标 - 用
ctx.beginPath()→ctx.moveTo()→ 多次ctx.lineTo()→ctx.closePath()绘制填充多边形;再单独描边轴线和网格圆
示例片段(省略样式设置):
立即学习“前端免费学习笔记(深入)”;
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const maxRadius = Math.min(centerX, centerY) * 0.8;
const angleStep = (Math.PI * 2) / data.length;
<p>ctx.beginPath();
for (let i = 0; i < data.length; i++) {
const angle = i <em> angleStep;
const r = (data[i] / maxValue) </em> maxRadius;
const x = centerX + r <em> Math.cos(angle);
const y = centerY + r </em> Math.sin(angle);
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fill();用
<svg></svg> 优势在于路径可声明、可动画、可绑定事件,且坐标系天然适合极坐标转换。关键不是用 <polyline></polyline>,而是用 <path></path> 的 d 属性拼接 M(move)和 L(line)指令。
- 每个顶点仍需手动算
x/y,但结果直接注入d字符串,无需 canvas 上下文状态管理 - 网格线可用
<circle></circle>(同心圆) +<line></line>(从中心出发的射线)组合,比 canvas 更易复用和修改 - 给
<path></path>加data-index="2"这类自定义属性,配合addEventListener('click')即可精准捕获点击的是第几个维度 - 注意 SVG 默认坐标原点在左上角,需用
viewBox或transform="translate()"把中心移到画布中点
别踩这些坑:坐标、归一化与响应式
实际项目中最常卡住的不是绘图逻辑,而是这三点:
-
Math.sin/Math.cos传了角度值(如 60),必须先转弧度:angleInRad = angleInDeg * Math.PI / 180 - 数据归一化没统一基准:若各维度量纲不同(如“响应速度:ms” vs “满意度:1–5 分”),不能直接用原始值除以全局
maxValue,得先做 min-max 或 z-score 标准化 - 响应式重绘时忘记重设
canvas.width/canvas.height(仅改 CSS 尺寸会导致图像模糊);SVG 则要监听resize并更新viewBox和transform
真正麻烦的从来不是画出一个静态图形,而是让角度对齐、半径比例合理、交互反馈明确——这些细节没有通用解,得根据你的数据分布和 UI 容器反复调。


















