讲师中心 微信公众号
AI工具推荐 视频效率加速

Chart.js 2.x 折线图特定Y轴区域背景着色与文本标注教程

阿明姑娘_7807

阿明姑娘_7807

发布时间:2025-11-25 14:57:02

|

996人浏览过

|

来源于php中文网

原创

Chart.js 2.x 折线图特定Y轴区域背景着色与文本标注教程

本教程旨在指导如何在 chart.js 2.x 折线图中,为特定的y轴数值范围添加自定义背景色和文本标注。文章将介绍两种实现方法:利用 `chartjs-plugin-annotation` 插件进行快速配置,以及通过编写自定义 chart.js 插件,在 `beforedraw` 钩子中直接使用 canvas api 进行精确绘制,以满足更灵活或无插件限制的需求。

在数据可视化中,有时我们需要突出图表中特定数值范围的重要性,例如用不同颜色标记“显著”或“严重”区域,并配以相应的文本说明。对于 Chart.js 2.x 版本的折线图,实现这一需求有多种途径。

方法一:使用 chartjs-plugin-annotation 插件

chartjs-plugin-annotation 是 Chart.js 的一个强大插件,它允许用户在图表上添加各种类型的注释,包括线、盒、文本等。对于 Chart.js 2.x 版本,推荐使用 chartjs-plugin-annotation 的 0.5.7 版本,以确保兼容性。

插件安装与配置

首先,通过 CDN 或 npm 引入插件:

<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>

然后,在 Chart.js 的 options 配置中,通过 annotation 属性来定义盒形和文本注释。您可以为每个需要着色的区域定义一个 box 类型注释来设置背景色,再定义一个 text 类型注释来添加文本标签。

options: {
    // ... 其他 Chart.js 选项
    annotation: {
        annotations: [{
            type: 'box',
            yScaleID: 'y-axis-0',
            yMin: 60,
            yMax: 80,
            backgroundColor: 'rgba(200, 200, 200, 0.5)', // 浅灰色
            borderColor: 'transparent'
        }, {
            type: 'label', // 或者 text
            yScaleID: 'y-axis-0',
            yValue: 70, // 文本居中位置
            xValue: 100, // 文本X轴位置,可能需要调整
            content: 'Significant',
            fontColor: '#000',
            fontSize: 14,
            position: 'right', // 文本位置
            xAdjust: -10 // 微调
        },
        // 为 80-100 范围添加类似配置
        {
            type: 'box',
            yScaleID: 'y-axis-0',
            yMin: 80,
            yMax: 100,
            backgroundColor: 'rgba(100, 100, 100, 0.5)', // 深灰色
            borderColor: 'transparent'
        }, {
            type: 'label',
            yScaleID: 'y-axis-0',
            yValue: 90,
            xValue: 100,
            content: 'Severe',
            fontColor: '#fff',
            fontSize: 14,
            position: 'right',
            xAdjust: -10
        }]
    }
}

这种方法配置简单,但对于非常精细的自定义绘制(例如特定样式的虚线或更复杂的文本布局),可能存在一定的局限性。

方法二:自定义 Chart.js 插件实现

当插件使用受限,或者需要更高度的自定义控制时,可以编写一个 Chart.js 自定义插件。通过利用 Chart.js 提供的插件核心 API,特别是 beforeDraw 钩子,我们可以在图表绘制之前直接在 Canvas 上进行绘制。

1. 插件原理概述

Chart.js 插件提供了一系列生命周期钩子函数,允许开发者在图表的不同绘制阶段介入。beforeDraw 钩子会在图表的数据集、轴线等元素绘制之前执行。这意味着我们可以在此阶段绘制背景区域和文本,而不会被后续的图表元素覆盖。

chartjs-reporter
chartjs-reporter

此技能用于在用户需要将结构化数据(查询结果、CSV 摘要、JSON 记录或 Python 字典/列表)转换为独立的 HTML 页面时使用。

下载

在 beforeDraw(chart) 钩子中,chart 参数提供了对整个图表实例的访问,包括其绘图上下文 (chart.ctx) 和所有轴 (chart.scales)。

2. 获取绘图上下文与轴信息

首先,在自定义插件的 beforeDraw 方法中,获取 Canvas 的 2D 绘图上下文 (ctx) 以及 X 轴和 Y 轴的引用:

plugins: [{
    beforeDraw(chart) {
        const ctx = chart.ctx;
        const xAxis = chart.scales['x-axis-0']; // 获取X轴实例,通常ID为'x-axis-0'
        const yAxis = chart.scales['y-axis-0']; // 获取Y轴实例,通常ID为'y-axis-0'

        // 获取X轴的左右边界像素坐标
        const xMin = xAxis.left;
        const xMax = xAxis.right;

        // 将Y轴的数值(如60, 80, 100)转换为对应的像素坐标
        const y100 = yAxis.getPixelForValue(100);
        const y80 = yAxis.getPixelForValue(80);
        const y60 = yAxis.getPixelForValue(60);

        // ... 后续绘制逻辑
    }
}]

yAxis.getPixelForValue(value) 方法是关键,它能将Y轴上的数据值转换为 Canvas 上的垂直像素坐标。

3. 绘制背景区域与文本标注

有了轴的像素坐标后,我们就可以使用 Canvas API 来绘制矩形背景和文本。

plugins: [{
    beforeDraw(chart) {
        const ctx = chart.ctx,
            xAxis = chart.scales['x-axis-0'],
            xMin = xAxis.left,
            xMax = xAxis.right,
            yAxis = chart.scales['y-axis-0'],
            y100 = yAxis.getPixelForValue(100),
            y80 = yAxis.getPixelForValue(80),
            y60 = yAxis.getPixelForValue(60);

        // 定义需要着色的区域及其对应的颜色和文本
        const bands = [
            [y60, y80, 'rgba(200, 200, 200, 0.8)', 'Significant'], // 60-80: 浅灰色
            [y80, y100, 'rgba(100, 100, 100, 0.8)', 'Severe'] // 80-100: 深灰色
        ];

        for (const [yStart, yEnd, color, text] of bands) {
            // 绘制背景矩形
            ctx.fillStyle = color;
            // fillRect(x, y, width, height)
            // x: X轴左边界, y: 区域顶部像素, width: X轴宽度, height: 区域高度
            ctx.fillRect(xMin, yStart, xMax - xMin, yEnd - yStart);

            // 添加文本标注
            ctx.fillStyle = '#fff'; // 文本颜色
            ctx.strokeStyle = 'rgba(0,0,0,0.3)'; // 文本描边颜色
            ctx.textAlign = 'right'; // 文本右对齐
            // 根据区域高度动态调整字体大小,并限制最大值
            ctx.font = Math.round(Math.min((yEnd - yStart) / 3, 48)) + 'px serif';
            ctx.textBaseline = 'middle'; // 文本垂直居中

            // 绘制文本 (fillText) 和描边文本 (strokeText)
            // text: 文本内容, x: X轴右边界-10px, y: 区域垂直中心
            ctx.fillText(text, xMax - 10, (yEnd + yStart) / 2);
            ctx.strokeText(text, xMax - 10, (yEnd + yStart) / 2);
        }
    }
}]

4. 完整的 Chart.js 配置示例

将上述自定义插件集成到 Chart.js 的配置中,即可实现预期效果。

<!DOCTYPE html>
<html>
<head>
    <title>Chart.js 特定区域背景着色</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js" integrity="sha512-zO8oeHCxetPn1Hd9PdDleg5Tw1bAaP0YmNvPY8CwcRyUk7d7/+nyElmFrB6f7vg4f7Fv4sui1mcep8RIEShczg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <style>
        body { margin: 0; overflow: hidden; }
        #lineChart { width: 99vw; height: 99vh; }
    </style>
</head>
<body>
    <canvas id="lineChart"></canvas>

    <script>
        var ctx = document.getElementById("lineChart").getContext("2d");
        var chart = new Chart(ctx, {
            type: "line",
            // 将自定义插件添加到 plugins 数组中
            plugins: [{
                beforeDraw(chart) {
                    const ctx = chart.ctx,
                        xAxis = chart.scales['x-axis-0'],
                        xMin = xAxis.left,
                        xMax = xAxis.right,
                        yAxis = chart.scales['y-axis-0'],
                        y100 = yAxis.getPixelForValue(100),
                        y80 = yAxis.getPixelForValue(80),
                        y60 = yAxis.getPixelForValue(60);

                    const bands = [
                        [y60, y80, 'rgba(200, 200, 200, 0.8)', 'Significant'],
                        [y80, y100, 'rgba(100, 100, 100, 0.8)', 'Severe']
                    ];

                    for (const [yStart, yEnd, color, text] of bands) {
                        ctx.fillStyle = color;
                        ctx.fillRect(xMin, yStart, xMax - xMin, yEnd - yStart);

                        ctx.fillStyle = '#fff';
                        ctx.strokeStyle = 'rgba(0,0,0,0.3)';
                        ctx.textAlign = 'right';
                        ctx.font = Math.round(Math.min((yEnd - yStart) / 3, 48)) + 'px serif';
                        ctx.textBaseline = 'middle';
                        ctx.fillText(text, xMax - 10, (yEnd + yStart) / 2);
                        ctx.strokeText(text, xMax - 10, (yEnd + yStart) / 2);
                    }
                }
            }],
            data: {
                labels: [
                    "",
                    "Working Memory",
                    "Inhibitory Control",
                    "Cognitive Flexibility",
                    "High Order EF",
                    "",
                ],
                datasets: [
                    {
                        label: "Competence score in Percent",
                        data: [null, 80, 65, 90, 75],
                        borderColor: ["#000", "#ffdb14", "#ff0000", "#38b7fe", "#8866f9"],
                        backgroundColor: [
                            "#000",
                            "#ffdb14",
                            "#ff0000",
                            "#38b7fe",
                            "#8866f9",
                        ],
                        fill: false,
                        pointRadius: 16,
                        pointHoverRadius: 8,
                        pointBackgroundColor: [
                            "#000",
                            "#ffdb14",
                            "#ff0000",
                            "#38b7fe",
                            "#8866f9",
                        ],
                        lineTension: 0,
                        borderColor: "#000",
                        borderWidth: 2,
                    },
                ],
            },
            options: {
                responsive: true,
                scales: {
                    xAxes: [
                        {
                            scaleLabel: {
                                display: true,
                                labelString: "Subtests",
                                fontSize: 24,
                            },
                            ticks: {
                                fontSize: 24,
                            },
                        },
                    ],
                    yAxes: [
                        {
                            scaleLabel: {
                                display: true,
                                labelString: "Competence score in Percent",
                                fontSize: 24,
                            },
                            ticks: {
                                beginAtZero: true,
                                min: 0,
                                max: 100,
                                stepSize: 25,
                                fontSize: 24,
                            },
                        },
                    ],
                },
                legend: {
                    display: false,
                },
            },
        });
    </script>
</body>
</html>

注意事项

  • Chart.js 版本兼容性: 本教程的代码主要针对 Chart.js 2.9.4 版本。Chart.js 3.x 及更高版本在插件 API 和轴的访问方式上有所不同,例如轴的 ID 可能会变为 x 和 y 而不是 x-axis-0。
  • 插件执行时机: beforeDraw 钩子在图表元素绘制之前执行,因此绘制的背景和文本会位于图表内容之下。如果需要覆盖图表内容,可以考虑使用 afterDraw 钩子。
  • 坐标转换: 理解 getPixelForValue() 的作用至关重要,它确保了数据值能够正确映射到 Canvas 上的像素位置。
  • Canvas API 基础: 熟悉基本的 Canvas 2D 绘图 API (如 fillRect, fillText, strokeText, fillStyle, font 等) 将有助于更灵活地自定义图表外观。
  • 响应式布局: 在响应式图表中,图表尺寸可能会变化。自定义插件中的坐标计算是基于当前的图表尺寸,因此通常能够很好地适应尺寸变化。

总结

为 Chart.js 折线图的特定Y轴区域添加背景色和文本标注,可以通过 chartjs-plugin-annotation 插件快速实现,也可以通过编写自定义 Chart.js 插件,在 beforeDraw 钩子中利用 Canvas API 进行更精细的控制。后者提供了最大的灵活性,适用于需要高度定制化或受限于不能使用额外插件的场景。选择哪种方法取决于具体的需求和项目约束。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4496

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1375

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1778

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

10043

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

980

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2804

2023.09.04

Js中concat和push的区别
Js中concat和push的区别

Js中concat和push的区别:1、concat用于将两个或多个数组合并成一个新数组,并返回这个新数组,而push用于向数组的末尾添加一个或多个元素,并返回修改后的数组的新长度;2、concat不会修改原始数组,是创建新的数组,而push会修改原数组,将新元素添加到原数组的末尾等等。本专题为大家提供concat和push相关的文章、下载、课程内容,供大家免费下载体验。

1569

2023.09.14

js截取字符串的方法介绍
js截取字符串的方法介绍

JavaScript字符串截取方法,包括substring、slice、substr、charAt和split方法。这些方法可以根据具体需求,灵活地截取字符串的不同部分。在实际开发中,根据具体情况选择合适的方法进行字符串截取,能够提高代码的效率和可读性 。

4809

2023.09.21

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

40

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB 17.2 官方文档集合
GDB 17.2 官方文档集合

共0课时 | 0人学习

Bootstrap 入门安装配置
Bootstrap 入门安装配置

共0课时 | 0人学习

38+ PhpStorm 提示和技巧
38+ PhpStorm 提示和技巧

共1课时 | 228人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn