Chart.js 极区图径向渐变实战:用 Scriptable 背景色与 Canvas 渐变打造立体 Polar Area 图表 📅 发布时间:2026/9/18 19:31:07 👁 浏览次数: Chart.js 极区图径向渐变实战用 Scriptable 背景色与 Canvas 渐变打造立体 Polar Area 图表【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js本文基于仓库 docs/samples/advanced/radial-gradient.md 提供的官方示例完整讲解如何在 Chart.js 极区图Polar Area Chart中通过elements.arc.backgroundColor的 Scriptable 配置为每个扇区注入基于 Canvas APIcreateRadialGradient生成的三色径向渐变并配合悬停hover状态与颜色缓存机制让图表在渲染性能与视觉效果上同时达标。读完本文你将掌握 Scriptable Options 的完整上下文结构、Canvas 渐变与 Chart.js 颜色工具链helpers.color/getHoverColor的组合用法以及如何规避初始渲染时 chartArea 尚不可用这一经典坑点。示例概览一个带随机化的渐变极区图该示例位于docs/samples/advanced/radial-gradient.md其核心是type: polarArea的图表共 5 个数据点标签取自月份Utils.months({count: 5})每个扇区根据dataIndex从一组 Chart.js 调色板颜色中取色再通过createRadialGradient3函数为每个扇区生成外圈亮色 → 中间过渡色 → 内圈深色的径向渐变背景。示例还注册了一个名为Randomize的 action点击后重新生成数据并调用chart.update()const actions [ { name: Randomize, handler(chart) { chart.data.datasets.forEach(dataset { dataset.data generateData(); }); chart.update(); } }, ];为什么极区图能接受渐变Arc 元素的 backgroundColor 解析链路要理解本例先要明白极区图与弧元素的关系。在 Chart.js 中极区图由 controller.polarArea.js 驱动其defaults中dataElementType: arc即每个扇区是一个 Arc 元素具体渲染逻辑在 element.arc.ts。Arc 元素绘制扇区填充时直接使用options.backgroundColorctx.fillStyle options.backgroundColor; ctx.strokeStyle options.borderColor;关键在于ArcElement的声明static defaultRoutes { backgroundColor: backgroundColor }; static descriptors { _scriptable: true, _indexable: (name) name ! borderDash };defaultRoutes.backgroundColor表示当 dataset 上未显式给出backgroundColor时会回退到元素级配置这正是示例使用options.elements.arc.backgroundColor的原因_scriptable: true表示backgroundColor是脚本化Scriptable选项可以传入函数函数在每次取值时为每个数据点执行一次并接收一个上下文对象context。因此示例中的写法elements: { arc: { backgroundColor: function(context) { // context.dataIndex 定位当前扇区 // 返回 string、CanvasGradient 或 CanvasPattern 均可 }, } }是完全合法的。Chart.js 的颜色解析工具 helpers.color.ts 中通过isPatternOrGradient检测值是否为CanvasGradient/CanvasPattern若是则原样透传而不做字符串解析export function color(value) { return isPatternOrGradient(value) ? value : new Color(value); }也就是说Canvas 渐变对象本身就是一个合法的颜色值可以直接作为backgroundColor返回——这正是本例的技术基石。更完整的极区图 dataset 属性borderAlign、borderDash、hoverBorderWidth、spacing、circular等可参考 docs/charts/polar.md。Scriptable 上下文context.dataIndex 与 context.active示例的渐变函数依赖 Scriptable 上下文中的两个关键字段backgroundColor: function(context) { let c colors[context.dataIndex]; if (!c) { return; } if (context.active) { c helpers.getHoverColor(c); } // ... }根据 docs/general/options.md 的 Option Context 定义元素级 Scriptable 函数收到的context属于data层级它继承dataset、chart两层信息包含chart关联的图表实例用于访问chart.chartArea、chart.ctxdataset/datasetIndex当前数据集及其索引dataIndex当前数据点扇区的索引active该元素当前是否处于激活悬停状态parsed/raw解析后的数值与原始数据。示例利用context.dataIndex从预设颜色数组中按索引取色颜色数量少于数据时会得到undefined此时直接return不返回颜色让浏览器/画布保持默认并利用context.active在悬停时切换为悬停色。悬停色的底层实现helpers.getHoverColor定义于 helpers.color.tsexport function getHoverColor(value) { return isPatternOrGradient(value) ? value : new Color(value).saturate(0.5).darken(0.1).hexString(); }它把传入颜色提高饱和度0.5、加深0.1再转回十六进制字符串。若传入的本来就是渐变/图案对象则原样返回。注意示例中传入的是字符串颜色chartColors.red等所以悬停时会得到一个加深后的新色值而createRadialGradient3的三个端点色都基于该悬停色重新计算悬停时整个扇区的渐变会同步变化。createRadialGradient3 逐行拆解构建三色径向渐变示例的核心函数createRadialGradient3(context, c1, c2, c3)接收 Scriptable 上下文与三个颜色值返回一个以图表绘图区中心为圆心、覆盖整个绘图区的径向渐变function createRadialGradient3(context, c1, c2, c3) { const chartArea context.chart.chartArea; if (!chartArea) { // This case happens on initial chart load return; } const chartWidth chartArea.right - chartArea.left; const chartHeight chartArea.bottom - chartArea.top; if (width ! chartWidth || height ! chartHeight) { cache.clear(); } let gradient cache.get(c1 c2 c3); if (!gradient) { width chartWidth; height chartHeight; const centerX (chartArea.left chartArea.right) / 2; const centerY (chartArea.top chartArea.bottom) / 2; const r Math.min( (chartArea.right - chartArea.left) / 2, (chartArea.bottom - chartArea.top) / 2 ); const ctx context.chart.ctx; gradient ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, r); gradient.addColorStop(0, c1); gradient.addColorStop(0.5, c2); gradient.addColorStop(1, c3); cache.set(c1 c2 c3, gradient); } return gradient; }1. 初始渲染的 chartArea 判空const chartArea context.chart.chartArea; if (!chartArea) { return; }chart.chartArea是图表绘图区去除了标题、图例、坐标轴等外围布局后的区域其left/right/top/bottom是布局完成后的像素坐标。在图表首次加载、布局尚未完成时chartArea可能为undefined此时无法计算尺寸函数直接返回undefined即不设置背景色。这是 Scriptable 函数必须做的防御性校验——docs/general/options.md 也明确提示context参数应在 Scriptable 函数中做校验因为函数会在不同上下文中被调用。2. 尺寸变化检测与渐变缓存if (width ! chartWidth || height ! chartHeight) { cache.clear(); }渐变依赖于绘图区尺寸圆心与半径随尺寸变化。模块级变量width/height记录上次生成渐变时的绘图区尺寸一旦检测到尺寸变化如窗口缩放、responsive触发重排就清空整个缓存强制下次重建所有渐变。3. 计算圆心与半径const centerX (chartArea.left chartArea.right) / 2; const centerY (chartArea.top chartArea.bottom) / 2; const r Math.min( (chartArea.right - chartArea.left) / 2, (chartArea.bottom - chartArea.top) / 2 );圆心取绘图区的几何中心半径取宽、高一半的较小值保证渐变圆始终内切于绘图区。4. 创建 Canvas 径向渐变const ctx context.chart.ctx; gradient ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, r); gradient.addColorStop(0, c1); gradient.addColorStop(0.5, c2); gradient.addColorStop(1, c3);context.chart.ctx是图表使用的 2D 画布上下文。createRadialGradient(x0, y0, r0, x1, y1, r1)定义两个同心圆起点圆半径为 0圆心点终点圆半径为r。随后通过三个addColorStop设置颜色断点0圆心c1—— 示例中为提亮 0.2 并色相旋转 270°的起始色0.5中点c2—— 示例中为去饱和 0.2 并加深 0.2的过渡色1外缘c3—— 示例中为提亮 0.1的结束色。5. 缓存命中与键设计cache.set(c1 c2 c3, gradient);渐变对象以c1 c2 c3拼接字符串为键存入Map。由于同一个扇区在重绘update()时会反复调用 Scriptable 函数而渐变的创建是相对昂贵的 Canvas 操作缓存可避免重复创建键中携带三个颜色值保证任一颜色变化例如悬停换色时能生成新的渐变条目。而尺寸变化时通过第 2 步的cache.clear()兜底清理。三色端点的颜色工程helpers.color 链式运算示例为每个基础色计算出三个渐变端点色const mid helpers.color(c).desaturate(0.2).darken(0.2).rgbString(); const start helpers.color(c).lighten(0.2).rotate(270).rgbString(); const end helpers.color(c).lighten(0.1).rgbString(); return createRadialGradient3(context, start, mid, end);这里的helpers.color是 Chart.js 暴露的颜色解析工具见 helpers.color.ts 的export function color(value)重载它将任意合法颜色字符串解析为kurkle/color的Color对象并支持链式变换lighten(0.2)/darken(0.2)按比例提亮 / 加深desaturate(0.2)按比例降低饱和度rotate(270)对色相做 270° 旋转即把基准色偏移到色环的另一侧产生互补感rgbString()输出rgb(r, g, b)字符串作为渐变端点色。设计意图很清晰start圆心用提亮 色相旋转的亮色mid中点用去饱和 加深的中间调end外缘用轻度提亮的基色。三者在同一个径向渐变中从圆心到外缘平滑过渡让扇区呈现类似高光 环境阴影的立体观感同时整套色系仍源自同一基准色整体协调统一。数据生成与工具函数示例的数据部分依赖文档站示例脚本 docs/scripts/utils.js 提供的工具Utils.srand(110); // 固定随机种子保证每次渲染数据一致 Utils.numbers({count: 5, min: 0, max: 100}); // 生成 5 个 0~100 的随机数 Utils.months({count: 5}); // 生成 5 个月份标签 Utils.CHART_COLORS // red/orange/yellow/green/blue 等预设色其中srand(seed)基于线性同余算法_seed (_seed * 9301 49297) % 233280实现可复现的伪随机序列固定种子110后每次刷新页面生成的随机数据都相同便于示例的视觉一致性。numbers支持min/max/count/decimals/continuity等参数continuity小于 1 时还会在数据中插入null极区图会将对应扇区跳过。极区图的数据结构本身要求datasets[].data为数值数组Chart.js 会自动求和并按比例分配角度见 docs/charts/polar.md 的 Data Structure 一节labels数组则用于图例与提示框。完整配置与运行方式把上述片段组合即可得到完整的可运行配置const config { type: polarArea, data: { labels: Utils.months({count: DATA_COUNT}), datasets: [{ data: generateData() }] }, options: { plugins: { legend: false, tooltip: false, }, elements: { arc: { backgroundColor: function(context) { let c colors[context.dataIndex]; if (!c) { return; } if (context.active) { c helpers.getHoverColor(c); } const mid helpers.color(c).desaturate(0.2).darken(0.2).rgbString(); const start helpers.color(c).lighten(0.2).rotate(270).rgbString(); const end helpers.color(c).lighten(0.1).rgbString(); return createRadialGradient3(context, start, mid, end); }, } } } };示例关闭了图例与提示框legend: false、tooltip: false把视觉焦点完全放在渐变扇区上。在实际项目中你可以保留图例此时图例色块取自meta.controller.getStyle(i).backgroundColor见 controller.polarArea.js 的 legendgenerateLabels覆写渐变颜色会被直接用作图例色块将渐变半径从Math.min(宽, 高) / 2调整为outerRadius让渐变严格贴合扇区外缘而非整个绘图区配合极区图的animation.animateRotate/animation.animateScale均默认true定义于 controller.polarArea.js 的defaults体验入场动画。运行该示例在仓库根目录安装依赖后启动文档站点docs/package.json提供文档构建脚本打开 Advanced → Radial Gradient 页面即可看到实时效果点击Randomize按钮可观察数据随机化后渐变与扇区角度的同步更新。关键要点回顾渐变即合法颜色CanvasGradient可被isPatternOrGradient识别并直接作为backgroundColor返回helpers.color.ts。Scriptable 上下文backgroundColor函数会在每个数据点上被调用context.dataIndex定位扇区、context.active反映悬停状态docs/general/options.md。必须防御 chartArea 为空初始渲染时chart.chartArea可能为undefined务必提前返回。缓存渐变对象以c1 c2 c3为键缓存渐变并在绘图区尺寸变化时cache.clear()兼顾重绘性能与响应式正确性。颜色工程链helpers.color(...).lighten()/darken()/desaturate()/rotate()/rgbString()可快速派生和谐的多级渐变端点色悬停色由getHoverColor饱和 加深统一处理。延伸阅读极区图完整文档数据集属性、样式、borderAlign、动画与默认覆盖Chart.overrides.polarAreaOptions 与 Scriptable Options选项解析层级、Option Context 全字段说明Arc 元素配置elements.arc下的borderRadius、offset、circular等更多弧元素样式示例工具脚本Utils.srand、Utils.numbers、Utils.months、CHART_COLORS等实现【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考