如何使用HTML5中Canvas绘制极坐标系实现动态的雷达扫描雷达图交互

作者:袖梨 2026-06-07
Canvas绘制极坐标系与雷达扫描动画的核心是:用三角函数计算点位、arc和lineTo构建坐标轴与网格、rotate+clearRect实现旋转扫描线、requestAnimationFrame驱动动态更新,并通过鼠标位置换算实时交互。

用 Canvas 绘制极坐标系并实现雷达扫描动画,核心在于:用三角函数计算点位、用 arclineTo 构建坐标轴与网格、用 rotate + clearRect 实现旋转扫描线、结合 requestAnimationFrame 做平滑动态更新。交互部分通过监听鼠标位置换算极坐标值,实时更新数据点即可。

绘制基础极坐标系(圆心+同心圆+射线)

先设定画布中心为原点 (cx, cy),半径 r 决定最大范围。用循环绘制 5–8 层同心圆(代表不同数值层级),再用角度步进(如每 30° 一条)画出放射状坐标轴线:

  • 同心圆:遍历 i = 1 to levelCount,半径为 r * i / levelCount,调用 ctx.arc(cx, cy, radius, 0, Math.PI * 2)
  • 射线:对每个角度 angle = i * Math.PI * 2 / rayCount,计算端点 x = cx + r * Math.cos(angle)y = cy + r * Math.sin(angle),再用 moveTolineTo 连线
  • 标注角度文字:用 ctx.fillText 在射线末端稍外侧显示角度或维度名(如“响应速度”“稳定性”)

实现雷达扫描线(旋转光束效果)

扫描线本质是一条从圆心出发、长度随时间增长再重置的射线,配合透明度渐变和尾迹模拟真实雷达感:

  • ctx.save()ctx.rotate(angle)ctx.beginPath()moveTo(cx, cy)lineTo(cx, cy - r) 画出当前角度的扫描线
  • 设置 ctx.strokeStyle = 'rgba(0, 180, 255, 0.8)',线宽 2–3,加 ctx.lineCap = 'round' 让末端更柔和
  • 每次帧更新时清空局部区域(非全屏):用 ctx.clearRect(cx - r - 10, cy - r - 10, r * 2 + 20, r * 2 + 20) 避免残留,再重绘静态坐标系(可缓存为离屏 canvas 提升性能)

将数据映射到极坐标并绘制雷达图多边形

假设有 n 个维度(如性能、兼容性、安全性…),每个维度值归一化到 [0, 1],对应半径比例。关键在把每个 (value, angle) 转为笛卡尔坐标:

立即学习“前端免费学习笔记(深入)”;

  • 预计算每维角度:angle[i] = i * Math.PI * 2 / n
  • 计算点坐标:x = cx + value[i] * r * Math.cos(angle[i])y = cy + value[i] * r * Math.sin(angle[i])
  • beginPath()moveTo(first) → 多次 lineTo()closePath()fill() 绘制填充多边形;叠加 stroke() 加轮廓
  • 支持动态更新:只需修改 value[] 数组,重绘多边形即可,无需重绘整个坐标系

添加鼠标交互:悬停获取极坐标值 & 点击编辑

监听 mousemoveclick,将屏幕坐标转为相对于圆心的向量,再解算极坐标:

  • 获取鼠标位置 rect = canvas.getBoundingClientRect(),计算 dx = x - rect.left - cxdy = y - rect.top - cy
  • 半径:rad = Math.sqrt(dx*dx + dy*dy);角度:theta = Math.atan2(dy, dx)(注意 atan2 返回 [-π, π],可转为 [0, 2π)
  • 映射到最近维度:取 index = Math.round(theta / (Math.PI * 2 / n)) % n,再根据 rad / r 得到该维度当前值估算
  • 点击时可触发编辑弹窗,或直接拖拽顶点更新数据数组

不复杂但容易忽略:Canvas 的坐标系 Y 轴向下,而数学极坐标 Y 向上,所以 sin 对应的是 dy 的负方向——实际写时用 y = cy - value * r * Math.sin(angle) 才符合常规雷达图朝上的视觉习惯。

相关文章

精彩推荐