HTML无法直接绘制气泡图,必须用Chart.js或D3.js实现;Chart.js最省事,原生支持bubble类型及自动缩放;D3更可控但需手动处理坐标与半径映射(r应取平方根)、交互和tooltip。

HTML 本身不支持直接绘制气泡图,必须借助 JavaScript 图表库或 SVG/Canvas 手动实现;纯 HTML+CSS 做不了真正的气泡图——它既无法响应数据变化,也不具备坐标映射、半径缩放、交互提示等核心能力。
用 Chart.js 实现响应式气泡图最省事
Chart.js 是目前最轻量、文档清晰、浏览器兼容性好的选择,bubble 类型原生支持三维数据(x, y, r),且自动处理坐标轴缩放和气泡大小归一化。
-
r字段代表气泡半径,单位是像素,但 Chart.js 内部会按数据范围做线性映射,所以传入的数值可以是原始业务值(比如用户数、销售额) - 必须为
x和y指定数值型数据,字符串坐标(如 “Q1”、“iOS”)会报TypeError: x value is not a number - 气泡颜色默认随机,想统一配色需显式设置
backgroundColor数组,长度要和数据点一致,否则会 fallback 到默认调色板 - 移动端 hover 提示失效,得启用
interaction: { mode: 'nearest', intersect: false }并配合plugins.tooltip配置触控响应
const ctx = document.getElementById('myBubbleChart').getContext('2d');
new Chart(ctx, {
type: 'bubble',
data: {
datasets: [{
label: 'Sales by Region',
data: [
{ x: 35, y: 50, r: 12000 }, // r 对应销售额,Chart.js 自动缩放到合理像素半径
{ x: 60, y: 20, r: 8500 },
{ x: 45, y: 75, r: 21000 }
],
backgroundColor: 'rgba(54, 162, 235, 0.6)'
}]
}
});用 D3.js 手动画气泡图更可控但要自己算缩放
D3 不提供开箱即用的 bubble 图类型,得用 d3.scaleLinear() 分别处理 x、y、r 三组数值到像素坐标的映射——这是最容易出错的地方。
-
r缩放不能直接用线性映射:人眼对面积敏感,气泡半径应与数据值的平方根成正比,否则小值几乎看不见,大值撑满画布。正确写法是radiusScale(d.value ** 0.5) - 如果数据含负值或零,
** 0.5会得 NaN,得先做偏移处理,例如Math.sqrt(d.value + offset) - D3 的
enter().append('circle')必须显式绑定cx、cy、r,漏掉任一属性会导致气泡不显示或位置错乱 - Tooltip 需监听
on('mouseover')并手动创建<div>浮层,还要用event.pageX/Y定位,否则在滚动页面时位置漂移
别碰纯 CSS 气泡图——它根本不是气泡图
网上有些“CSS 气泡图”只是用 border-radius: 50% 和绝对定位堆几个圆,这种方案连最基本的数据驱动都做不到:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- 气泡大小无法随数据动态调整,改一个
width就得手调所有left/top值 - 没有坐标轴,x/y 值只能靠估算,误差超过 10px 就看不出趋势
- 加 tooltip 要每个圆单独写
::after,数据一多就爆炸式增加 CSS 规则 - 响应式布局下,
vw/vh单位会让气泡在不同屏幕缩放失真,因为半径和位置没走同一套比例逻辑
导出高清 PNG 或 PDF 时注意 canvas 像素密度
用 Chart.js 或 D3 渲染的 canvas 在高 DPI 屏幕(Mac Retina、Windows 缩放 125%+)上截图模糊,是因为 canvas 默认渲染分辨率为物理像素的一半。
- 修复方法是在创建 canvas 前读取
window.devicePixelRatio,然后手动放大 canvas 的width/height属性,并用 CSS 缩回显示尺寸 - Chart.js 用户可直接用插件
chartjs-plugin-zoom或社区方案chartjs-node-canvas(服务端渲染)绕过浏览器限制 - D3 用户导出 SVG 更稳妥:
d3.select('svg').node().outerHTML取出字符串再转 PDF,无像素损失,但文件体积大、复杂动画不保留
真正麻烦的从来不是“怎么画个圆”,而是让每个圆的位置、大小、颜色、交互都严格对应数据语义,并在不同设备、缩放、导出场景下保持一致——这些细节藏在 scale 函数里、devicePixelRatio 判断里、tooltip 的事件委托里,漏掉一个,图就只是看起来像气泡图而已。


















