资讯详情

资讯详情

Chart.js Tooltip 插件完全指南:配置项、回调机制与外部 HTML Tooltip 实战

Chart.js Tooltip 插件完全指南配置项、回调机制与外部 HTML Tooltip 实战【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js本篇技术指南围绕 Chart.js 官方文档中的 Tooltip 章节对应仓库 docs/configuration/tooltip.md展开系统梳理 Tooltip 的完整配置模型、回调函数体系、定位模式与外部自定义 Tooltip 的实现方案。读完本文你将掌握如何通过配置与回调精确控制 Canvas 内 Tooltip 的外观与行为并能独立实现 HTML 形式的自定义 Tooltip。Tooltip 配置总览Tooltip 是 Chart.js 的独立插件其配置命名空间为options.plugins.tooltip图表全局默认值定义在Chart.defaults.plugins.tooltip。你可以在创建图表时按实例配置也可以直接修改全局默认值影响所有图表。在源码 src/plugins/plugin.tooltip.js#L1275-L1350 中可以看到完整的默认配置定义其核心选项与默认值如下表名称类型默认值说明enabledbooleantrue是否启用 Canvas 上绘制的 Tooltipexternalfunctionnull外部自定义 Tooltip 函数见下文「External (Custom) Tooltips」modestringinteraction.mode决定哪些元素会出现在 Tooltip 中取值见 interaction modesintersectbooleaninteraction.intersect为true时仅在鼠标位置与元素相交时应用 mode为false时 mode 始终生效positionstringaverageTooltip 定位模式见「Position Modes」callbacksobject回调对象见「Tooltip Callbacks」itemSortfunction对 Tooltip 条目排序见「Sort Callback」filterfunction过滤 Tooltip 条目见「Filter Callback」backgroundColorColorrgba(0, 0, 0, 0.8)Tooltip 背景色titleColorColor#fff标题文字颜色titleFontFont{weight: bold}标题字体见 FontstitleAlignstringleft标题文本水平对齐见「Text Alignment」titleSpacingnumber2每个标题行的上下间距titleMarginBottomnumber6标题区底部外边距bodyColorColor#fff主体文本颜色bodyFontFont{}主体字体bodyAlignstringleft主体文本水平对齐bodySpacingnumber2每个 Tooltip 条目的上下间距footerColorColor#fff底部文本颜色footerFontFont{weight: bold}底部字体footerAlignstringleft底部文本水平对齐footerSpacingnumber2每个底部行的上下间距footerMarginTopnumber6绘制底部区域前的边距paddingPadding6Tooltip 内边距caretPaddingnumber2箭头末端与 Tooltip 点的额外距离caretSizenumber5箭头大小pxcornerRadiusnumber|object6Tooltip 圆角半径multiKeyBackgroundColor#fff多个条目时色块后方的背景色displayColorsbooleantrue是否在 Tooltip 中显示色块boxWidthnumberbodyFont.size启用displayColors时色块宽度boxHeightnumberbodyFont.size启用displayColors时色块高度boxPaddingnumber1源码默认0色块与文本之间的内边距usePointStylebooleanfalse使用数据集中的点样式星形、三角形等代替色块尺寸取boxWidth与boxHeight的较小值borderColorColorrgba(0, 0, 0, 0)边框颜色borderWidthnumber0边框宽度rtlboolean为true时从右向左渲染 TooltiptextDirectionstringcanvas 默认强制指定 canvas 上 Tooltip 的文本方向rtl或ltr不受 canvas 的 CSS 影响xAlignstringundefinedTooltip 箭头在 X 方向的位置见「Tooltip Alignment」yAlignstringundefinedTooltip 箭头在 Y 方向的位置:::warningtitleFont、bodyFont与footerFont默认继承Chart.defaults.font。要覆盖这些默认值必须传入一个返回字体对象的函数详见下文「Default font overrides」。 :::需要说明两点源码与文档的差异文档表格中boxPadding默认值为1而源码 src/plugins/plugin.tooltip.js#L1307 中写的是0实际以源码为准另外文档标注padding默认值为6与源码一致。如果你需要更丰富的视觉定制如富文本、复杂布局官方建议改用 HTML Tooltip参考 docs/samples/tooltip/html.md。配置解析机制Tooltip 的配置并非简单读取对象属性。从源码可以看到additionalOptionScopes: [interaction]plugin.tooltip.js#L1349表示mode、intersect等未显式设置的值会回退到interaction命名空间解析描述符plugin.tooltip.js#L1333-L1346定义了哪些选项支持 scriptablefilter、itemSort、external三个函数选项不参与 scriptable 解析而callbacks对象整体也不参与 scriptable/indexable 解析动画默认值plugin.tooltip.js#L1310-L1323中numbers动画作用于x、y、width、height、caretX、caretY六个位置属性时长 400msopacity动画为线性缓动、时长 200ms。Position Modes定位模式Tooltip 支持两种内置定位模式通过position选项选择average将 Tooltip 放置在所显示条目的平均位置nearest将 Tooltip 放置在离事件位置最近元素的位置。源码 src/plugins/plugin.tooltip.js#L17-L91 中positioners对象的实现细节可以印证两者差异average模式收集每个条目的element.tooltipPosition()对 X 坐标去重后取平均、对 Y 坐标直接取平均当没有任何可见元素或 X 坐标集合为空时返回false避免除零产生 NaN。nearest模式则用distanceBetweenPoints计算事件位置到每个元素中心点的距离选取距离最小的元素再取其tooltipPosition()作为锚点。除内置模式外你还可以注册自定义定位模式见下文「Custom Position Modes」。Tooltip Alignment箭头对齐xAlign与yAlign决定 Tooltip 箭头caret的位置。若这两个参数未设置Chart.js 会根据 Tooltip 相对图表画布的位置自动确定最优箭头位置。xAlign支持的值leftcenterrightyAlign支持的值topcenterbottom自动对齐的计算发生在源码的determineAlignment与getBackgroundPoint函数中plugin.tooltip.js#L304-L329getBackgroundPoint会根据箭头尺寸、caretPadding以及圆角半径计算 Tooltip 背景的精确位置并通过_limitValue将 Tooltip 约束在图表画布范围内防止溢出。Text Alignment文本对齐titleAlign、bodyAlign、footerAlign决定文本行相对 Tooltip 盒子的水平位置支持的值left默认rightcenter注意这些选项只作用于文本行色块始终对齐到左边缘。getAlignedXplugin.tooltip.js#L331-L339展示了具体计算逻辑——center时文本起始位置为tooltip.x tooltip.width / 2right时为tooltip.x tooltip.width - padding.rightleft时为tooltip.x padding.left。Sort Callback排序回调itemSort用于对 Tooltip 条目排序。该函数必须至少是一个可传给Array.prototype.sort的函数接收(a, b)两个 TooltipItem还可以接收第三个参数——传给图表的 data 对象。在源码 plugin.tooltip.js#L619-L621 中排序发生在_createItems内部tooltipItems tooltipItems.sort((a, b) options.itemSort(a, b, data));Filter Callback过滤回调filter用于从 Tooltip 中过滤条目函数至少是一个可传给Array.prototype.filter的函数也可以接收第四个参数 data 对象。源码 plugin.tooltip.js#L614-L616 中的调用方式tooltipItems tooltipItems.filter((element, index, array) options.filter(element, index, array, data));测试用例 test/specs/plugin.tooltip.tests.js#L768-L792 给出了典型场景根据数据集上的自定义属性隐藏 Tooltip 条目filter: function(tooltipItem, index, tooltipItems, data) { // 移除带有 tooltipHidden 属性的数据集条目 return !data.datasets[tooltipItem.datasetIndex].tooltipHidden; }Tooltip Callbacks回调体系命名空间为options.plugins.tooltip.callbacks。所有回调中this指向由Tooltip构造函数创建的 Tooltip 对象。若回调返回undefined则使用默认回调若想从 Tooltip 中移除某些内容回调应返回空字符串。命名空间data.datasets[].tooltip.callbacks允许按数据集覆盖回调下表中标注Dataset override为Yes的回调都可以按数据集覆盖。源码中的overrideCallbacksplugin.tooltip.js#L356-L359实现了这一机制当数据集的dataset.tooltip.callbacks存在时会用其覆盖全局回调并作用于beforeLabel、label、afterLabel、labelColor、labelTextColor、labelPointStyle这几个逐条目回调。每个出现在 Tooltip 中的条目都会生成一个 Tooltip item context这是回调方法交互的主要模型。返回文本的函数中字符串数组会被当作多行文本渲染splitNewlines还会把含\n的字符串拆成多行见 plugin.tooltip.js#L113-L118。名称参数返回类型数据集覆盖说明beforeTitleTooltipItem[]string \| string[] \| undefined在标题之前渲染的文本titleTooltipItem[]string \| string[] \| undefined作为 Tooltip 标题渲染的文本afterTitleTooltipItem[]string \| string[] \| undefined在标题之后渲染的文本beforeBodyTooltipItem[]string \| string[] \| undefined在主体区之前渲染的文本beforeLabelTooltipItemstring \| string[] \| undefinedYes在单个标签之前渲染的文本对每个条目调用labelTooltipItemstring \| string[] \| undefinedYes单个条目的文本见「Label Callback」labelColorTooltipItemobject \| undefinedYes条目的颜色见「Label Color Callback」labelTextColorTooltipItemColor \| undefinedYes条目文本颜色labelPointStyleTooltipItemobject \| undefinedYesusePointStyle为true时使用的点样式含pointStyle与rotation字段。默认实现使用数据集点的样式见「Label Point Style Callback」afterLabelTooltipItemstring \| string[] \| undefinedYes在单个标签之后渲染的文本afterBodyTooltipItem[]string \| string[] \| undefined在主体区之后渲染的文本beforeFooterTooltipItem[]string \| string[] \| undefined在底部区之前渲染的文本footerTooltipItem[]string \| string[] \| undefined作为 Tooltip 底部渲染的文本afterFooterTooltipItem[]string \| string[] \| undefined在底部区之后渲染的文本源码中默认回调定义在defaultCallbacksplugin.tooltip.js#L361-L436其行为可供参考默认title回调返回第一个条目的 label若mode为dataset则返回数据集 label默认label回调返回数据集名: 格式化值默认labelColor从数据集控制器获取条目的borderColor、backgroundColor、borderWidth、borderDash、borderDashOffset、borderRadius默认labelTextColor返回options.bodyColor默认labelPointStyle返回数据集点的pointStyle与rotationbeforeTitle、afterTitle、beforeBody、beforeLabel、afterLabel、afterBody、beforeFooter、footer、afterFooter默认为空操作noop。回退机制由invokeCallbackWithFallbackplugin.tooltip.js#L447-L455实现先调用用户回调若结果严格为undefined则回退到默认回调。Label Callbacklabel回调可以改变某个数据点显示的文本常见用法是追加单位。下面的例子在每个数据行前加$const chart new Chart(ctx, { type: line, data: data, options: { plugins: { tooltip: { callbacks: { label: function(context) { let label context.dataset.label || ; if (label) { label : ; } if (context.parsed.y ! null) { label new Intl.NumberFormat(en-US, { style: currency, currency: USD }).format(context.parsed.y); } return label; } } } } } });Label Color Callback例如让 Tooltip 中的每个条目显示红色背景、蓝色虚线边框并带圆角的色块const chart new Chart(ctx, { type: line, data: data, options: { plugins: { tooltip: { callbacks: { labelColor: function(context) { return { borderColor: rgb(0, 0, 255), backgroundColor: rgb(255, 0, 0), borderWidth: 2, borderDash: [2, 2], borderRadius: 2, }; }, labelTextColor: function(context) { return #543453; } } } } } });Label Point Style CallbackusePointStyle: true时可用labelPointStyle让每个条目绘制三角形等点样式替代常规色块const chart new Chart(ctx, { type: line, data: data, options: { plugins: { tooltip: { usePointStyle: true, callbacks: { labelPointStyle: function(context) { return { pointStyle: triangle, rotation: 0 }; } } } } } });Tooltip Item Context传给回调的 Tooltip 条目实现以下接口{ // Tooltip 所在的图表 chart: Chart, // Tooltip 的标签 label: string, // 给定 dataIndex 和 datasetIndex 对应的解析后数据值 parsed: object, // 给定 dataIndex 和 datasetIndex 对应的原始数据值 raw: object, // 格式化后的值 formattedValue: string, // 条目所属的数据集 dataset: object, // 数据集索引 datasetIndex: number, // 该数据项在数据集中的索引 dataIndex: number, // 该 Tooltip 条目对应的图表元素point、arc、bar 等 element: Element, }源码中的createTooltipItemplugin.tooltip.js#L127-L143是构造该上下文的地方label与formattedValue来自数据集控制器的getLabelAndValue(index)parsed来自controller.getParsed(index)raw直接取chart.data.datasets[datasetIndex].data[index]。External (Custom) Tooltips外部自定义 Tooltip外部 Tooltip 允许你挂接到 Tooltip 渲染流程中用完全自定义的方式渲染 Tooltip最常见的用途是创建 HTML Tooltip 替代 Canvas 内绘制。external选项接收一个函数该函数被传入包含chart和tooltip的 context 参数。你可以在全局或图表配置中启用const myPieChart new Chart(ctx, { type: pie, data: data, options: { plugins: { tooltip: { // 禁用 Canvas 内 Tooltip enabled: false, external: function(context) { // Tooltip 元素 let tooltipEl document.getElementById(chartjs-tooltip); // 首次渲染时创建元素 if (!tooltipEl) { tooltipEl document.createElement(div); tooltipEl.id chartjs-tooltip; tooltipEl.innerHTML table/table; document.body.appendChild(tooltipEl); } // 无 Tooltip 时隐藏 const tooltipModel context.tooltip; if (tooltipModel.opacity 0) { tooltipEl.style.opacity 0; return; } // 设置箭头位置 tooltipEl.classList.remove(above, below, no-transform); if (tooltipModel.yAlign) { tooltipEl.classList.add(tooltipModel.yAlign); } else { tooltipEl.classList.add(no-transform); } function getBody(bodyItem) { return bodyItem.lines; } // 设置文本 if (tooltipModel.body) { const titleLines tooltipModel.title || []; const bodyLines tooltipModel.body.map(getBody); let innerHtml thead; titleLines.forEach(function(title) { innerHtml trth title /th/tr; }); innerHtml /theadtbody; bodyLines.forEach(function(body, i) { const colors tooltipModel.labelColors[i]; let style background: colors.backgroundColor; style ; border-color: colors.borderColor; style ; border-width: 2px; const span span style style body /span; innerHtml trtd span /td/tr; }); innerHtml /tbody; let tableRoot tooltipEl.querySelector(table); tableRoot.innerHTML innerHtml; } const position context.chart.canvas.getBoundingClientRect(); const bodyFont Chart.helpers.toFont(tooltipModel.options.bodyFont); // 显示、定位并设置字体样式 tooltipEl.style.opacity 1; tooltipEl.style.position absolute; tooltipEl.style.left position.left window.pageXOffset tooltipModel.caretX px; tooltipEl.style.top position.top window.pageYOffset tooltipModel.caretY px; tooltipEl.style.font bodyFont.string; tooltipEl.style.padding tooltipModel.padding px tooltipModel.padding px; tooltipEl.style.pointerEvents none; } } } } });外部 Tooltip 的入门示例可参考 docs/samples/tooltip/html.md。在源码层面Tooltip 插件的afterEvent钩子plugin.tooltip.js#L1264-L1273会在事件到达后调用tooltip.handleEvent并把args.changed置为true触发重绘beforeTooltipDraw/afterTooltipDraw两个插件通知点plugin.tooltip.js#L1254-L1260则环绕在tooltip.draw周围可供其他插件介入绘制。Tooltip ModelTooltip 模型外部 Tooltip 函数中拿到的context.tooltip即 Tooltip 模型包含渲染所需的全部参数{ chart: Chart, // 正在渲染的条目数组见 Tooltip Item Context 一节 dataPoints: TooltipItem[], // 定位 xAlign: string, yAlign: string, // x、y 为 Tooltip 左上角坐标 x: number, y: number, width: number, height: number, // Tooltip 指向的位置 caretX: number, caretY: number, // 主体 // 需要渲染的主体行每个对象包含 3 个参数 // before: string[] // 色块行之前的文本行 // lines: string[], // 带色块的主文本行 // after: string[], // 主文本行之后的文本行 body: object[], // 标题之后、主体之前出现的文本行 beforeBody: string[], // 主体之后、底部之前出现的文本行 afterBody: string[], // 标题构成标题的文本行 title: string[], // 底部构成底部的文本行 footer: string[], // body[] 中每个条目的渲染样式即 Tooltip 中色块的样式 labelColors: TooltipLabelStyle[], labelTextColors: Color[], labelPointStyles: { pointStyle: PointStyle; rotation: number }[], // opacity 为 0 表示隐藏的 Tooltip opacity: number, // Tooltip 选项 options: Object }在源码的update方法plugin.tooltip.js#L638-L677中可以清楚地看到模型如何被填充当没有激活元素时若当前opacity非 0 则只更新opacity: 0隐藏动画否则依次调用定位器、构建条目与各段文本getTitle、getBeforeBody、getBody、getAfterBody、getFooter计算尺寸并确定对齐与背景点最终把x、y、width、height、caretX、caretY、opacity等属性一并写入动画系统实现平滑的移动与淡入淡出。Custom Position Modes自定义定位模式可以通过向Chart.Tooltip.positioners映射表添加函数来定义新模式import { Tooltip } from chart.js; /** * 自定义定位器 * function Tooltip.positioners.myCustomPositioner * param elements {Chart.Element[]} Tooltip 元素 * param eventPosition {Point} 事件在 canvas 坐标系中的位置 * returns {TooltipPosition} Tooltip 位置 */ Tooltip.positioners.myCustomPositioner function(elements, eventPosition) { // 指向 Tooltip 模型的引用 const tooltip this; /* ... */ return { x: 0, y: 0 // 也可以返回 xAlign 和 yAlign 来覆盖对应的 Tooltip 选项 }; }; // 然后这样使用 new Chart(ctx, { data, options: { plugins: { tooltip: { position: myCustomPositioner } } } });更详细的示例见 docs/samples/tooltip/position.md。源码中定位器注册在Tooltip.positioners静态属性上plugin.tooltip.js#L457-L462update时通过positioners[options.position].call(this, active, this._eventPosition)调用plugin.tooltip.js#L651其中this即 Tooltip 实例本身。测试用例 test/specs/plugin.tooltip.tests.js#L1042-L1090 验证了自定义定位器的调用约定第一个参数是元素数组第二个参数包含x、y的事件位置且函数作用域this为 Tooltip 实例。若使用 TypeScript还需要注册新模式declare module chart.js { interface TooltipPositionerMap { myCustomPositioner: TooltipPositionerFunctionChartType; } }Default font overrides默认字体覆盖默认情况下titleFont、bodyFont和footerFont会读取Chart.defaults.font选项来取值。直接访问并修改对象属性是无效的因为这些属性背后是一个查找默认font命名空间的 get 函数源码中的defaultRoutes定义见 plugin.tooltip.js#L1327-L1331bodyFont: font、footerFont: font、titleFont: font。因此你需要用返回目标配置的函数覆盖这个 get 函数。示例Chart.defaults.plugins.tooltip.titleFont () ({ size: 20, lineHeight: 1.2, weight: 800 });实战建议小结只改文案优先使用callbacks中的title、label、footer返回值支持字符串数组实现多行文本定制外观组合backgroundColor、cornerRadius、borderWidth、padding、titleFont等外观选项注意titleFont需要函数形式才能绕过字体默认值需要复杂交互或富文本关闭enabled使用external渲染 HTML Tooltip通过 Tooltip Model 的caretX/caretY、body、labelColors等字段驱动 DOM 布局多数据集场景善用itemSort、filter控制展示顺序与内容或用data.datasets[].tooltip.callbacks按数据集覆盖逐条目回调需要特殊落点通过Tooltip.positioners注册自定义定位模式并记得在 TypeScript 的TooltipPositionerMap中登记类型。以上配置、回调与外部 Tooltip 机制共同构成了 Chart.js Tooltip 插件的完整能力边界配合 docs/configuration/interactions.md 中mode/intersect的取值说明与 docs/samples/tooltip/ 下的示例文档即可在实际项目中灵活落地。【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →