ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Chart.js 图例(Legend)配置完全指南:选项、事件钩子与源码实现解析

Chart.js 图例(Legend)配置完全指南:选项、事件钩子与源码实现解析 Chart.js 图例Legend配置完全指南选项、事件钩子与源码实现解析【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.jsChart.js 的图例Legend插件通过options.plugins.legend命名空间驱动负责在图表上展示数据集的颜色方块、文字标签并支持点击切换可见性。本文围绕官方文档 docs/configuration/legend.md 展开完整覆盖图例的位置position/align、标签labels、标题title等全部配置项结合 src/plugins/plugin.legend.js 的源码实现剖析布局测量、命中检测与默认点击行为的底层逻辑并给出自定义onClick、联动数据集、HTML 图例等可直接复制的实战方案。图例插件的角色与全局默认值图例显示的是出现在图表上的数据集的数据。在 Chart.js 中图例是一个内置插件 一个参与布局layout的盒子命名空间options.plugins.legend全局默认值定义在Chart.defaults.plugins.legend源码中插件的默认值见 plugin.legend.js 的 defaultsdisplay: true、position: top、align: center、fullSize: true、reverse: false、weight: 1000并内置了默认的onClick处理函数。需要注意一个重要的特例doughnut环形图、pie饼图、polarArea极区图会覆盖图例默认值。要修改这几类图表的图例覆盖项需通过Chart.overrides[type].plugins.legend设置。从源码结构看环形图的控制器在 controller.doughnut.js 的 static overrides 中重写了labels.generateLabels——饼图/环形图只有一个数据集但每个数据点都是独立一项因此默认按data.labels逐个生成图例项文字取labelhidden状态对应的是getDataVisibility(i)而非数据集可见性。pie 与 polarArea 控制器继承该行为。配置选项总表options.plugins.legend支持以下顶层选项完整继承自官方文档NameTypeDefaultDescriptiondisplaybooleantrue是否显示图例positionstringtop图例位置见下文 位置Position。alignstringcenter图例对齐方式见下文 对齐Align。maxHeightnumber图例最大高度像素maxWidthnumber图例最大宽度像素fullSizebooleantrue标记该盒子应占满画布宽度/高度并挤压其他盒子。日常使用很少改动。onClickfunction点击图例标签项时触发的回调。参数[event, legendItem, legend]。onHoverfunction鼠标在标签项上方移动时触发。参数[event, legendItem, legend]。onLeavefunction鼠标移出之前悬停的标签项时触发。参数[event, legendItem, legend]。reversebooleanfalse反转数据集的显示顺序。labelsobject见下文 图例标签配置。rtlbooleantrue表示从右向左渲染图例。textDirectionstring画布默认强制图例文本方向为rtl或ltr无论画布上 CSS 指定什么。titleobject见下文 图例标题配置。如果需要更多视觉层面的定制例如 DOM 化的图例列表官方推荐配合 HTML 图例方案参见示例 docs/samples/legend/html.md。另外从源码的 descriptors 可以看出配置解析规则顶层除on*开头的事件回调外都支持 scriptable函数式写法labels子项中generateLabels、filter、sort明确不可 scriptable。位置Positionposition的可选值topleftbottomrightchartArea使用chartArea时图例的具体位置目前不可配置它会始终位于图表区域的左侧中部。源码中位置直接决定了图例的测量方式isHorizontal()仅当position top || bottom时返回true即left/right都走垂直布局多列向下增长top/bottom走水平布局多行向右增长。位置切换后布局系统需要在下一帧重新生效插件在 beforeUpdate 钩子 中重新执行layouts.configure确保位置选项更新时被布局系统尊重。动态修改位置的典型写法摘自示例 docs/samples/legend/position.mdchart.options.plugins.legend.position right; chart.update();对齐Alignalign的可选值startcenterend无法识别的取值会回退到center。从源码看对齐在两个地方生效命中盒子的位置修正adjustHitBoxes与绘制光标起点_draw中 cursor 初始化两者都通过_alignStartEnd(align, start, end)在贴边 / 居中 / 贴另一端之间插值。标题同样使用align与自身的position参与对齐计算见 drawTitle。图例标签配置labels命名空间options.plugins.legend.labelsNameTypeDefaultDescriptionboxWidthnumber40颜色方块的宽度。boxHeightnumberfont.size颜色方块的高度。colorColorChart.defaults.color标签文字与删除线的颜色。fontFontChart.defaults.font见 字体Fonts。paddingnumber10行与行之间颜色方块的间距。generateLabelsfunction为图例中的每一项生成图例对象。默认实现返回色块的文本 样式。详见下文 图例项接口。filterfunctionnull过滤掉不显示的图例项。接收 2 个参数图例项 和图表数据。sortfunctionnull对图例项排序。签名为sort(a: LegendItem, b: LegendItem, data: ChartData): number。返回值的语义与Array.prototype.sort()的返回值一致。pointStylepointStylecircle若指定图例使用该点样式。仅当usePointStyle为true时生效。textAlignstringcenter标签文字的水平对齐。可选left、right、center。usePointStylebooleanfalse标签样式与对应点样式一致尺寸取pointStyleWidth或boxWidth与font.size的较小值。pointStyleWidthnumbernullusePointStyle为true时图例点样式的宽度。useBorderRadiusbooleanfalse标签圆角与对应数据集的borderRadius一致。borderRadiusnumberundefined覆盖要使用的圆角值。几个与源码对应的实现细节方块尺寸计算getBoxSize中boxHeight默认取fontSizeboxWidth也默认取fontSizeboxWidth: 40是默认配置值当usePointStyle为true时boxHeight Math.min(boxHeight, fontSize)boxWidth pointStyleWidth || Math.min(boxWidth, fontSize)这正对应文档中尺寸基于 pointStyleWidth 或 boxWidth 与 font.size 的最小值的说明。label 颜色是 scriptable 的默认配置中labels.color定义为(ctx) ctx.chart.options.color见 defaults.labels即默认跟随图表级color选项而不是一个固定的Chart.defaults.color。generateLabels / filter / sort 的执行顺序在buildLabels中依次执行——先调用generateLabels回调为null时回退为空数组再filter、再sort最后按reverse: true反转。由于afterUpdate钩子会在每次数据集更新后重新buildLabels源码注释指出这是为了保证颜色等样式正确因此修改数据颜色后图例会自动同步。图例标题配置title命名空间options.plugins.legend.titleNameTypeDefaultDescriptioncolorColorChart.defaults.color文字颜色。displaybooleanfalse是否显示图例标题。fontFontChart.defaults.font见 字体Fonts。paddingPadding0标题四周的内边距。textstring标题文本。源码中title的默认值还包括position: center见 defaults.title用于标题在图例内的左/中/右对齐。标题高度由_computeTitleHeight计算为font.lineHeight padding.heightdisplay: false时为 0并参与行/列布局的总高度。标题配置示例可参考 docs/samples/legend/title.md。图例项接口Legend Item传给图例onClick函数的是labels.generateLabels返回的对象这些对象必须实现以下接口{ // 显示的文字 text: string, // 图例项的圆角。 // 3.1.0 引入 borderRadius?: number | BorderRadius, // 关联数据集的索引 datasetIndex: number, // 图例方块的填充样式 fillStyle: Color, // 文字颜色 fontColor: Color, // 若为 true表示该项对应一个隐藏的数据集标签会渲染删除线效果 hidden: boolean, // 方块边框样式。见 CanvasRenderingContext2D.lineCap lineCap: string, // 方块边框。见 CanvasRenderingContext2D.setLineDash lineDash: number[], // 方块边框。见 CanvasRenderingContext2D.lineDashOffset lineDashOffset: number, // 方块边框。见 CanvasRenderingContext2D.lineJoin lineJoin: string, // 方块边框宽度 lineWidth: number, // 图例方块的描边样式 strokeStyle: Color, // 图例方块的点样式仅 usePointStyle 为 true 时使用 pointStyle: string | Image | HTMLCanvasElement, // 点的旋转角度单位度仅 usePointStyle 为 true 时使用 rotation: number }默认generateLabels的实现defaults.labels.generateLabels遍历chart._getSortedDatasetMetas()从meta.controller.getStyle()取每个数据集的backgroundColor/borderColor/borderDash等样式填入图例项其中text取自datasets[meta.index].labelhidden取自!meta.visible绘制时fillText会据此渲染删除线见renderText调用处的strikethrough: legendItem.hiddenborderRadius仅在useBorderRadius: true时取borderRadius || style.borderRadius绘制时通过toTRBLCorners转换后用addRoundedRectPath画圆角方块见drawLegendBox。基础示例显示图例并把文字设为红色以下示例创建一个启用图例的柱状图并将所有图例文字设为红色继承自官方文档const chart new Chart(ctx, { type: bar, data: data, options: { plugins: { legend: { display: true, labels: { color: rgb(255, 99, 132) } } } } });若希望图例符号使用数据集的点样式而非矩形方块可配合usePointStyle示例见 docs/samples/legend/point-style.mdoptions: { plugins: { legend: { labels: { usePointStyle: true, // 可选 pointStyleWidth 控制宽度 } } } }自定义 onClick 行为图例项点击后触发不同行为是很常见的需求可以直接在配置对象中用回调实现。默认的图例点击处理函数是function(e, legendItem, legend) { const index legendItem.datasetIndex; const ci legend.chart; if (ci.isDatasetVisible(index)) { ci.hide(index); legendItem.hidden true; } else { ci.show(index); legendItem.hidden false; } }这段逻辑与源码中 defaults 里注册的 onClick 完全一致可见则hide并打上删除线标记隐藏则show并恢复。假如想让前两个数据集的显示状态联动可以替换点击处理函数const defaultLegendClickHandler Chart.defaults.plugins.legend.onClick; const pieDoughnutLegendClickHandler Chart.controllers.doughnut.overrides.plugins.legend.onClick; const newLegendClickHandler function (e, legendItem, legend) { const index legendItem.datasetIndex; const type legend.chart.config.type; if (index 1) { // 执行原有逻辑 if (type pie || type doughnut) { pieDoughnutLegendClickHandler(e, legendItem, legend) } else { defaultLegendClickHandler(e, legendItem, legend); } } else { let ci legend.chart; [ ci.getDatasetMeta(0), ci.getDatasetMeta(1) ].forEach(function(meta) { meta.hidden meta.hidden null ? !ci.data.datasets[index].hidden : null; }); ci.update(); } }; const chart new Chart(ctx, { type: line, data: data, options: { plugins: { legend: { onClick: newLegendClickHandler } } } });这样点击图例时前两个数据集的可见性就会联动切换。注意示例中从Chart.controllers.doughnut.overrides取出饼图/环形图的覆盖版点击处理正好呼应了前文环形图覆盖了图例默认值的说明。事件分发机制与 onHover / onLeave图例的事件入口是handleEvent其分发规则值得注意先判断是否有监听器isListened中只有配置了onHover/onLeave时才处理mousemove/mouseout只有配置了onClick时才处理click/mouseup命中检测_getLegendItemAt先用_isBetween确认点击落在图例盒子范围内再逐一比对legendHitBoxes测量阶段在_fitRows/_fitCols中生成、在adjustHitBoxes中修正到最终坐标返回命中的legendItems[i]悬停状态跟踪mousemove/mouseout时用itemsEqual比较datasetIndex与index判断是否换到了新项——离开旧项调onLeave进入新项调onHover点击其余事件类型click/mouseup命中图例项后调用onClick。事件回调的实战写法可参考 docs/samples/legend/events.md该示例在悬停某图例项时给其他数据点的背景色追加 alpha 通道color 4D实现高亮移出后还原并在回调末尾调用legend.chart.update()重绘function handleHover(evt, item, legend) { legend.chart.data.datasets[0].backgroundColor.forEach((color, index, colors) { colors[index] index item.index || color.length 9 ? color : color 4D; }); legend.chart.update(); }布局测量、RTL 与绘制流程理解fit()源码有助于调参display为false时直接置零宽高返回水平图例top/bottom宽度取满maxWidth高度由_fitRows按itemWidth boxWidth fontSize/2 measureText(text).width逐行装箱超过maxWidth - 2*padding就换行最终 10像素余量垂直图例left/right高度取满maxHeight宽度由_fitCols按列装箱超出高度上限时开新列最后用options.maxWidth/options.maxHeight钳制实际宽高——这就是顶层maxWidth/maxHeight选项的生效位置。RTL 支持通过getRtlAdapter(opts.rtl, this.left, this.width)见_draw镜像所有 x 坐标与textAligntextDirection则在绘制前后通过overrideTextDirection/restoreTextDirection强制画布文本方向。文字绘制统一走renderText来自 helpers.canvas.ts 的封装支持labels.textAlign与逐项的legendItem.textAlign。验证方式仓库中图例相关的回归测试集中在 test/specs/plugin.legend.tests.js覆盖点击、悬停、位置、对齐等行为像素级渲染对比则位于 test/fixtures/plugin.legend/ 下的若干子目录例如 标题与对齐、label textAlign、边框圆角、maxWidth 限制 与 RTL 命中盒。可以对照这些夹具文件名快速确认各配置项的渲染预期。小结命名空间options.plugins.legend控制显示、位置top/left/bottom/right/chartArea、对齐start/center/end、尺寸上限、RTL/文本方向以及onClick/onHover/onLeave事件钩子labels子命名空间控制方块与文字样式并通过generateLabels/filter/sort三个函数完全接管图例内容的生成、过滤与排序title子命名空间提供可开关的图例标题饼图/环形图/极区图通过控制器overrides重写了generateLabels与点击行为定制时需走Chart.overrides[type].plugins.legend深度定制DOM 化图例、自定义容器可基于labels.generateLabels的内置生成函数自行构建 HTML 图例参见 docs/samples/legend/html.md。【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表