Worker是唯一能解耦雷达图计算与渲染的方案,需配合分片、通信控制和坐标预处理:归一化与极坐标转换移至Worker,按chunkSize分片处理并动态调优,主线程仅负责调度、渲染与交互。

直接在主线程里算雷达图的极坐标点、归一化、路径填充,遇到几百个维度或上万条数据时,页面立马卡死。Worker 是唯一能真正解耦计算与渲染的方案——但光扔进 Worker 不行,必须配合分片、通信控制和坐标预处理。
把归一化和坐标转换逻辑全移到 Worker 里
雷达图最耗时的不是画图,是每维数据独立归一化 + 极坐标转直角坐标的循环计算。这些纯数学运算不该占主线程。在 worker.js 中封装完整流程:
- 接收原始数据数组、各维度 min/max(或让 Worker 自动统计)、画布尺寸、中心点、最大半径
- 对每个维度执行归一化:(value - min) / (max - min || 1),防除零
- 按维度数 n 计算每项角度:angle = −Math.PI/2 + i * 2*Math.PI / n(顶部朝上)
- 算出每个顶点:x = centerX + radius * normValue * Math.cos(angle),同理算 y
- 返回所有顶点坐标数组,不包含任何绘图操作
必须分片执行,否则 Worker 自身也会“假死”
哪怕在 Worker 里,单次处理 10 万条数据仍会阻塞其内部消息循环——主线程发来的暂停指令收不到,fetch 回调不触发,Chrome 还可能标红警告“Worker unresponsive”。解决方法是主动分片:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 把数据按 chunkSize(如 500 条)切块,每次只处理一块
- 每块结束后用 setTimeout(processNextChunk, 0) 或 Promise.resolve().then(processNextChunk) 让出控制权
- 在每块开头检查中断标志:if (shouldCancel) return;收到 cancel 消息就立刻清空并 postMessage({ type: 'cancelled' })
- 初始 chunkSize 可设为 200,运行中用 performance.now() 测每块耗时,动态调整(如超 8ms 就减半)
主线程只负责调度、渲染和交互响应
主线程彻底解放:它不再碰数据计算,只做三件事:
立即学习“前端免费学习笔记(深入)”;
- 创建 Worker 实例,监听 onmessage 接收坐标数组或状态消息(done/cancelled/pause)
- 拿到坐标后,用 Canvas 2D API 快速绘制:beginPath → moveTo → lineTo × n → closePath → fill
- 用户拖拽缩放、悬停查看数值?这些 DOM 事件完全不被阻塞,可实时更新 canvas 或显示 tooltip
支持多组数据叠加与动态重绘
如果要对比 5 个员工的能力雷达图,不要让 Worker 一次性算完全部——改用“流水线”方式:
- 主线程依次向 Worker 发送每组数据:worker.postMessage({ type: 'process', data: emp1Data })
- Worker 处理完一组,立即回传坐标;主线程收到就立刻绘制该组(不同颜色+透明度)
- 需要刷新?先 ctx.clearRect() 清空,再等新坐标流进来重绘,无须锁住 UI
- 若某组数据量特别大,可在 Worker 内部启动子 Worker 并行处理(高级场景,需注意浏览器并发限制)


















