ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Chart.js 气泡图 Scriptable 选项实战:用回调函数驱动颜色、半径与悬浮态

Chart.js 气泡图 Scriptable 选项实战:用回调函数驱动颜色、半径与悬浮态 Chart.js 气泡图 Scriptable 选项实战用回调函数驱动颜色、半径与悬浮态【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js导读本文以 Chart.js 官方示例 docs/samples/scriptable/bubble.md 为骨架完整剖析如何通过 Scriptable脚本化选项让气泡图的每个数据点拥有独立的颜色、边框与半径。你将掌握context参数的使用方法、elements.point各属性回调的写法以及 Chart.js 内部如何解析半径并驱动动画与悬浮交互可直接复制示例代码到你的项目中运行验证。示例全景一个数据驱动的气泡图原始示例生成 16 个数据点每个点携带x、y、v三个维度通过 scriptable 选项将v映射为颜色透明度与半径大小最终形成一个数据密度可视化的散点气泡图const DATA_COUNT 16; const MIN_XY -150; const MAX_XY 100; Utils.srand(110); const actions [ { name: Randomize, handler(chart) { chart.data.datasets.forEach(dataset { dataset.data generateData(); }); chart.update(); } }, ]; function generateData() { const data []; let i; for (i 0; i DATA_COUNT; i) { data.push({ x: Utils.rand(MIN_XY, MAX_XY), y: Utils.rand(MIN_XY, MAX_XY), v: Utils.rand(0, 1000) }); } return data; } const data { datasets: [{ data: generateData() }, { data: generateData() }] }; function channelValue(x, y, values) { return x 0 y 0 ? values[0] : x 0 ? values[1] : y 0 ? values[2] : values[3]; } function colorize(opaque, context) { const value context.raw; const x value.x / 100; const y value.y / 100; const r channelValue(x, y, [250, 150, 50, 0]); const g channelValue(x, y, [0, 50, 150, 250]); const b channelValue(x, y, [0, 150, 150, 250]); const a opaque ? 1 : 0.5 * value.v / 1000; return rgba( r , g , b , a ); } const config { type: bubble, data: data, options: { aspectRatio: 1, plugins: { legend: false, tooltip: false, }, elements: { point: { backgroundColor: colorize.bind(null, false), borderColor: colorize.bind(null, true), borderWidth: function(context) { return Math.min(Math.max(1, context.datasetIndex 1), 8); }, hoverBackgroundColor: transparent, hoverBorderColor: function(context) { return Utils.color(context.datasetIndex); }, hoverBorderWidth: function(context) { return Math.round(8 * context.raw.v / 1000); }, radius: function(context) { const size context.chart.width; const base Math.abs(context.raw.v) / 1000; return (size / 24) * base; } } } } }; module.exports { actions, config, };这段代码在chart-editor代码块内运行依赖文档示例专用的Utils工具见 docs/samples/utils.md。Utils.srand(110)固定随机种子保证每次刷新图表数据一致Utils.rand(min, max)生成区间内的随机数——这两个函数只用于示例与测试环境官方明确提示生产环境不要依赖Utils文件。气泡图数据的三维结构气泡图与传统散点图的核心区别在于用三个维度表达信息x、y决定气泡位置第三个维度决定气泡大小。官方文档 docs/charts/bubble.md 给出的标准数据结构为{ x: number, // X 值 y: number, // Y 值 r: number // 气泡半径像素不随坐标缩放 }其中r是未缩放的原始像素半径由 Chart.js 直接绘制在画布上。而本示例中的v字段是一个自定义维度它不直接参与渲染而是通过 scriptable 回调在运行时计算透明度0.5 * value.v / 1000和半径Math.abs(context.raw.v) / 1000这正是 scriptable 选项的典型用法——原始数据中任何字段都可以在回调中读取并参与样式计算。内部数据格式与半径解析数据在进入渲染管线后会被解析为内部格式{x, y, _custom}其中_custom就是半径。从 src/controllers/controller.bubble.js 的parseObjectData可以看到parseObjectData(meta, data, start, count) { const parsed super.parseObjectData(meta, data, start, count); for (let i 0; i parsed.length; i) { const item data[start i]; parsed[i]._custom valueOrDefault(item item.r item.r, this.resolveDataElementOptions(i start).radius); } return parsed; }即如果数据对象提供了r直接采用否则回退到elements.point.radius的解析值。随后在 resolveDataElementOptions 中_custom与解析出的radius相加得到最终渲染半径非激活非悬浮状态下radius会被临时置为 0保证普通状态只用_custom的半径值。这解释了为什么脚本化radius回调的返回值是基准半径而数据里的r是叠加半径。Scriptable 选项机制回调如何驱动样式Scriptable 选项的核心是选项值可以是一个函数Chart.js 会为每个数据点调用该函数并传入context上下文对象详见 docs/general/options.md#scriptable-options。本示例为backgroundColor、borderColor、borderWidth、hoverBorderColor、hoverBorderWidth、radius六个属性都使用了回调。选项解析的分层作用域Scriptable 回调解析遵循自顶向下的作用域链docs/general/options.md#option-resolution元素级选项依次查找dataset→options.datasets[type].elements[elementType]→options.elements[elementType]→options→overrides[...]→defaults[...]气泡图的dataElementType为point因此options.elements.point是气泡样式的标准挂载点见 controller.bubble.js 的defaults定义。示例中所有回调都写在options.elements.point下作用于全部数据集的所有气泡。context 上下文回调的数据来源context是 scriptable 回调唯一的参数包含以下常用字段docs/general/options.md#data字段含义chart当前 Chart 实例可读取chart.width等布局信息dataIndex当前数据点的索引datasetIndex当前数据集的索引raw当前数据点的原始数据对象如{x, y, v}parsed解析后的数据如{x, y, _custom}active元素是否处于激活悬浮状态type上下文类型如data、dataset颜色回调按象限配色colorize函数利用channelValue将平面按x、y正负划分为四个象限为每个象限分配不同的 RGB 通道值再用value.v控制透明度function channelValue(x, y, values) { return x 0 y 0 ? values[0] : x 0 ? values[1] : y 0 ? values[2] : values[3]; } function colorize(opaque, context) { const value context.raw; const x value.x / 100; const y value.y / 100; const r channelValue(x, y, [250, 150, 50, 0]); const g channelValue(x, y, [0, 50, 150, 250]); const b channelValue(x, y, [0, 150, 150, 250]); const a opaque ? 1 : 0.5 * value.v / 1000; return rgba( r , g , b , a ); }这里用colorize.bind(null, false)/colorize.bind(null, true)预绑定opaque参数让同一个函数同时服务填充色半透明和边框色不透明。v越大透明度越高颜色越实。半径回调随图表宽度自适应radius回调将气泡半径与画布宽度挂钩使图表在任意尺寸下都能保持协调的比例radius: function(context) { const size context.chart.width; const base Math.abs(context.raw.v) / 1000; return (size / 24) * base; }v的取值范围0–1000被归一化到0–1再乘以width / 24。注意这里使用了Math.abs即使用户传入负的v值也能得到合法半径。边框宽度回调数据集序号的间接映射borderWidth: function(context) { return Math.min(Math.max(1, context.datasetIndex 1), 8); }该回调把datasetIndex映射到 1–8 像素第一个数据集边框 1px第二个 2px依此类推用Math.min/Math.max做了上下限钳制。气泡图通常最多十几个数据集这种写法保证了边框粗细始终处于合理区间。悬浮态hover 系列选项的脚本化示例为悬浮态定义了三个脚本化选项与一个静态选项hoverBackgroundColor: transparent, // 悬浮时填充变为全透明 hoverBorderColor: function(context) { return Utils.color(context.datasetIndex); // 按数据集序号取预设调色板颜色 }, hoverBorderWidth: function(context) { return Math.round(8 * context.raw.v / 1000); // 按 v 值 0-8 取整 },悬浮交互的底层逻辑可以参考 src/elements/element.point.tspoint元素默认定义了hoverRadius: 4、hitRadius: 1、hoverBorderWidth: 1等默认值。结合 test/specs/controller.bubble.tests.js 的测试用例可以验证悬浮时radius会在基础半径上叠加hoverRadius如测试中20 4移出后恢复为20且hoverBackgroundColor、hoverBorderColor、hoverBorderWidth均会被单独解析——这意味着 hover 系列同样支持完整的脚本化能力。测试用例佐证controller.bubble.tests.js 还验证了数据集级 hover 属性的优先级当在chart.data.datasets[0]上定义hoverBackgroundColor、hoverRadius等属性并chart.update()后悬浮态样式立即生效鼠标移出后恢复数据集与元素级配置。这印证了文档中hover 属性未定义时回退到elements.point.*的解析规则docs/charts/bubble.md#interactions。运行与验证在 Chart.js 的文档环境中该示例以chart-editor代码块形式渲染并导出actions与config页面上的 Randomize 按钮会重新生成数据并调用chart.update()。若要在自己的项目中使用引入 Chart.js 并注册BubbleController与PointElement将config直接传给new Chart(ctx, config)在本地复制示例时用真实的Math.random()或固定数据替换Utils依赖因为Utils仅为文档示例服务见 docs/samples/utils.md 的免责声明。运行限制提示气泡图默认需要线性坐标轴——controller.bubble.js 的overrides中自动为x、y轴配置了type: linear因此本示例无需显式声明scales。相关文档气泡图完整配置项数据集属性、默认值、数据格式docs/charts/bubble.md选项解析与 Scriptable/Indexable 机制docs/general/options.mdScriptable Options、Option Context示例工具函数srand、rand、color等docs/samples/utils.md其余 scriptable 示例bar、line、pie、polar、radardocs/samples/scriptable【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表