Skip to content

获取渐变颜色中某个百分比位置的颜色

约 2316 字大约 8 分钟

cssjs

2025-08-28

本文将详细解释如何通过 JavaScript 实现根据百分比获取渐变颜色的功能。其核心在于 线性插值 (Linear Interpolation) 算法,并将其应用于颜色的红、绿、蓝三个分量。


1. 核心原理:线性插值 (Linear Interpolation)

该功能的核心在于对颜色分量进行线性插值。线性插值是一种在两个已知点之间,根据一个比例因子,估算出中间点值的方法。

通用线性插值公式:

给定起始值 V1V1 和结束值 V2V2,以及一个比例因子 pp(范围通常为 0 到 1),中间值 VV 的计算公式为:

V=V1+(V2−V1)×pV=V1+(V2−V1)×p


2. 颜色表示 (Color Representation)

在数字世界中,颜色通常通过 RGB (Red, Green, Blue) 模型来表示,每个分量的取值范围是 0 到 255。

  • 红色 (red): [255, 0, 0]
  • 黄色 (yellow): [255, 255, 0]
  • 黑色 (black): [0, 0, 0]
  • 白色 (white): [255, 255, 255]

我们的 getGradientColor 函数直接接收 [R, G, B] 数组作为输入,简化了颜色解析的步骤,确保了输入颜色的格式统一。


3. 百分比标准化 (Percentage Normalization)

用户输入的百分比是 0 到 100 之间的一个整数。为了方便在数学计算中应用线性插值公式,我们需要将其转换为一个 0 到 1 之间的小数(比例因子)。

  • 转换公式: p = percentage / 100

在代码中,我们还加入了边界检查,以确保 p 的值严格在 [0, 1] 范围内,防止因用户输入超出 0-100 范围的百分比而导致计算错误:

const p = Math.max(0, Math.min(1, percentage / 100));
  • percentage 为 0 时,p 为 0。
  • percentage 为 50 时,p 为 0.5。
  • percentage 为 100 时,p 为 1。

4. 线性插值计算 (核心步骤)

由于 RGB 颜色的三个分量(红、绿、蓝)是相对独立的,我们可以对每个分量分别应用线性插值公式。

假设起始颜色为 rgb1 = [R1, G1, B1],结束颜色为 rgb2 = [R2, G2, B2],比例因子为 p

  • 红色分量 (R):r = R1 + (R2 - R1) * p
  • 绿色分量 (G):g = G1 + (G2 - G1) * p
  • 蓝色分量 (B):b = B1 + (B2 - B1) * p

举例说明 (从 redyellow,在 80% 位置的颜色)

  1. 起始颜色 (red): rgb1 = [255, 0, 0]
  2. 结束颜色 (yellow): rgb2 = [255, 255, 0]
  3. 百分比: 80%,标准化后 p = 0.8
  • 计算红色分量 r: r = 255 + (255 - 255) * 0.8 = 255 + 0 * 0.8 = 255
  • 计算绿色分量 g: g = 0 + (255 - 0) * 0.8 = 0 + 255 * 0.8 = 204
  • 计算蓝色分量 b: b = 0 + (0 - 0) * 0.8 = 0 + 0 * 0.8 = 0

因此,在 80% 位置的颜色是 [255, 204, 0]

JavaScript 代码实现 getGradientColor 函数

/**
 * 根据百分比获取两个颜色之间的渐变色。
 * 此函数假定输入的颜色已经是 RGB 数组格式。
 *
 * @param {number[]} rgb1 - 起始颜色 [R, G, B] 数组 (例如: [255, 0, 0] 代表红色)。
 *                          每个分量应在 0-255 之间。
 * @param {number[]} rgb2 - 结束颜色 [R, G, B] 数组 (例如: [255, 255, 0] 代表黄色)。
 *                          每个分量应在 0-255 之间。
 * @param {number} percentage - 渐变百分比 (0-100)。
 * @returns {string} - 计算出的颜色,以 CSS 的 rgb() 格式字符串返回 (例如: "rgb(255, 128, 0)")。
 */
function getGradientColor(rgb1, rgb2, percentage) {
    // 将输入的百分比转换为 0 到 1 之间的小数,并确保其在此范围内。
    // Math.max(0, ...) 确保不小于 0。
    // Math.min(1, ...) 确保不大于 1。
    const p = Math.max(0, Math.min(1, percentage / 100));

    // 对 R (红), G (绿), B (蓝) 三个颜色分量分别进行线性插值计算。
    // 公式:startComponent + (endComponent - startComponent) * p
    // Math.round() 用于将浮点数结果四舍五入为最接近的整数,因为 RGB 分量必须是整数。
    const r = Math.round(rgb1[0] + (rgb2[0] - rgb1[0]) * p);
    const g = Math.round(rgb1[1] + (rgb2[1] - rgb1[1]) * p);
    const b = Math.round(rgb1[2] + (rgb2[2] - rgb1[2]) * p);

    // 返回 CSS 的 rgb() 格式字符串。
    return `rgb(${r}, ${g}, ${b})`;
}

5. 结果处理与输出 (Result Processing)

  1. 四舍五入: 线性插值计算出来的 R, G, B 值可能是浮点数。然而,CSS 的 rgb() 函数要求颜色分量是 0 到 255 之间的整数。因此,我们使用 Math.round() 对每个计算出的分量进行四舍五入,得到最接近的整数值。
  2. 格式化输出: 最后,将这三个整数分量组合成一个 CSS 兼容的 rgb() 字符串,例如 rgb(255, 204, 0)

总结

总而言之,该功能通过将复杂的“颜色渐变”问题,分解为对颜色三个独立分量(红、绿、蓝)的简单线性插值计算。通过将起始颜色和结束颜色的每个分量视为一个数值,然后根据给定的百分比,在这个数值区间内找到对应的中间值,最终再将这些中间值组合成新的颜色。这种方法直观、高效,是实现平滑颜色过渡的关键。


完整代码示例

以下是包含 HTML、CSS 和 JavaScript 的完整代码,可以直接保存为 .html 文件并在浏览器中运行,以体验此功能。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>渐变颜色获取 (无 parseColor)</title>
    <style>
        /* #grad 元素样式:用于展示原始的 CSS 渐变效果 */
        #grad {
            width: 200px; /* 宽度 */
            height: 50px; /* 高度 */
            /* 定义一个从红色到黄色的线性渐变背景 */
            background-image: linear-gradient(to right, red, yellow);
            margin-bottom: 20px; /* 底部外边距,与下方元素隔开 */
        }

        /* #resultColorBox 元素样式:用于显示计算出的颜色块 */
        #resultColorBox {
            width: 50px; /* 宽度 */
            height: 50px; /* 高度 */
            border: 1px solid #ccc; /* 灰色边框 */
            display: inline-block; /* 行内块级元素,使其与文本在同一行 */
            vertical-align: middle; /* 垂直居中对齐 */
            margin-left: 10px; /* 左侧外边距 */
        }
    </style>
</head>

<body>
    <h1>根据百分比获取渐变颜色 (直接使用 RGB 数组)</h1>
    <p>原始渐变 (red 到 yellow):</p>
    <div id="grad"></div> <!-- 用于展示原始渐变的 div -->

    <div>
        <label for="percentageInput">输入百分比 (0-100):</label>
        <!-- 数字输入框,用于用户输入百分比 -->
        <input type="number" id="percentageInput" value="80" min="0" max="100">
        <!-- 按钮,点击时触发颜色计算函数 -->
        <button onclick="calculateAndDisplayColor()">获取颜色</button>
    </div>

    <p>
        <!-- 显示当前计算的百分比 -->
<span id="displayPercentage">80</span>% 位置的颜色:
        <!-- 显示计算出的颜色值 (rgb 字符串) -->
        <span id="resultColorText"></span>
        <!-- 显示计算出的颜色块 -->
        <div id="resultColorBox"></div>
    </p>

    <script>
        /**
         * 根据百分比获取两个颜色之间的渐变色。
         * 此函数假定输入的颜色已经是 RGB 数组格式。
         *
         * @param {number[]} rgb1 - 起始颜色 [R, G, B] 数组 (例如: [255, 0, 0] 代表红色)。
         *                          每个分量应在 0-255 之间。
         * @param {number[]} rgb2 - 结束颜色 [R, G, B] 数组 (例如: [255, 255, 0] 代表黄色)。
         *                          每个分量应在 0-255 之间。
         * @param {number} percentage - 渐变百分比 (0-100)。
         * @returns {string} - 计算出的颜色,以 CSS 的 rgb() 格式字符串返回 (例如: "rgb(255, 128, 0)")。
         */
        function getGradientColor(rgb1, rgb2, percentage) {
            // 将输入的百分比转换为 0 到 1 之间的小数,并确保其在此范围内。
            // Math.max(0, ...) 确保不小于 0。
            // Math.min(1, ...) 确保不大于 1。
            const p = Math.max(0, Math.min(1, percentage / 100));

            // 对 R (红), G (绿), B (蓝) 三个颜色分量分别进行线性插值计算。
            // 公式:startComponent + (endComponent - startComponent) * p
            // Math.round() 用于将浮点数结果四舍五入为最接近的整数,因为 RGB 分量必须是整数。
            const r = Math.round(rgb1[0] + (rgb2[0] - rgb1[0]) * p);
            const g = Math.round(rgb1[1] + (rgb2[1] - rgb1[1]) * p);
            const b = Math.round(rgb1[2] + (rgb2[2] - rgb1[2]) * p);

            // 返回 CSS 的 rgb() 格式字符串。
            return `rgb(${r}, ${g}, ${b})`;
        }

        // 示例使用:
        // 直接定义起始和结束颜色的 RGB 数组。
        // 'red' 对应的 RGB 值
        const startColorRGB = [255, 0, 0];
        // 'yellow' 对应的 RGB 值
        const endColorRGB = [255, 255, 0];

        /**
         * 计算并显示渐变颜色。
         * 此函数从用户输入获取百分比,然后调用 getGradientColor 函数,
         * 并将结果更新到页面上。
         */
        function calculateAndDisplayColor() {
            // 获取百分比输入框的 DOM 元素
            const percentageInput = document.getElementById('percentageInput');
            // 将输入框的值解析为整数
            let percentage = parseInt(percentageInput.value);

            // 验证用户输入的百分比是否有效 (0-100 之间)
            if (isNaN(percentage) || percentage < 0 || percentage > 100) {
                alert("请输入一个介于 0 到 100 之间的有效百分比。");
                return; // 如果无效则停止执行
            }

            // 调用 getGradientColor 函数,传入预定义的 RGB 数组和用户输入的百分比
            const resultColor = getGradientColor(startColorRGB, endColorRGB, percentage);

            // 获取用于显示结果的 DOM 元素
            const resultColorTextElement = document.getElementById('resultColorText');
            const resultColorBoxElement = document.getElementById('resultColorBox');
            const displayPercentageElement = document.getElementById('displayPercentage');

            // 更新页面上的文本和颜色块
            resultColorTextElement.textContent = resultColor; // 显示 rgb() 字符串
            resultColorBoxElement.style.backgroundColor = resultColor; // 设置颜色块的背景色
            displayPercentageElement.textContent = percentage; // 更新显示的百分比
        }

        // 页面加载完成时,自动执行一次 calculateAndDisplayColor 函数,
        // 以便在页面初次加载时显示默认的 80% 颜色。
        document.addEventListener('DOMContentLoaded', calculateAndDisplayColor);
    </script>
</body>

</html>