用原生 JS 做可交互数据可视化(零依赖)
经验驱动。不引 ECharts、不接 CDN,纯 SVG + 原生 JS 手搓一个可交互柱状图(附
p2_js_viz.html,支持 hover 提示、打乱、升降序),JS 已用 node 校验。为什么不用库、怎么画、交互怎么做、高分屏怎么不糊,全在这里。
为什么不用图表库
ECharts 好用,但引入就要几百 KB;CDN 不稳(面试现场断网就尴尬);而且面试官想看的是你会不会画,不是你会不会调 API。手搓一个 SVG 柱状图,既能进博客当 demo,又能当面试谈资——“坐标映射 + 事件绑定”这两件事讲清楚,比背配置项值钱。
怎么画:核心是坐标映射
柱状图本质是一个线性映射:数据值 v → 矩形高度 h。
1 | var max = Math.max.apply(null, data.map(d => d.v)); |
x 方向按 数据条数 均分,每条留点间隙。坐标轴和文字都是 <line> / <text> 元素。
怎么交互:事件委托 + 重绘
- hover 提示:给每个
<rect>绑mousemove,用position:fixed的 tip 跟着clientX/clientY走,显示data-k / data-v。 - 打乱 / 排序:纯数组操作(
sort/ Fisher–Yates),改完数据再调一次render()重绘。 - 重绘用
svg.innerHTML = s:比逐个createElement省事得多;关键在于重绘后重新绑定事件——我用事件委托(在重绘的 rect 上统一加监听)避免重复绑定泄漏。
真跑校验:
1 | node -e "const fs=require('fs');const h=fs.readFileSync('p2_js_viz.html','utf8'); |
踩坑实录
- SVG 重绘的命名空间:
svg.innerHTML = "<rect.../>"在浏览器里能正确解析成 SVG 元素(浏览器会按上下文推断命名空间),比手动createElementNS简单。别在<svg>里用document.createElement画元素,会画不出。 - 高分屏不糊:SVG 是矢量的,缩放天然清晰;如果你用
<canvas>,必须乘devicePixelRatio放大画布再scale回去,否则 Retina 上发虚。这也是我选 SVG 的原因之一。 - tooltip 定位:用
position:fixed+ 视口坐标(clientX/Y),别用absolute+ 文档坐标,滚动后会对不上。 - 动画别过度:
transition:fill .15s只做颜色过渡,布局变化(高度)别加 transition,否则重绘时柱子会”抽风”式伸缩。
小结
零依赖可视化的套路就三步:① 值→高度的坐标映射;② innerHTML 一次性重绘;③ 事件委托做交互。掌握这套,柱状图、折线、散点都能举一反三。面试聊”前端基本功”时,这比”我会用 ECharts”更有说服力。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 河岳日星的博客!

