如何从 HTML 页面中的 3 个输入范围正确获取 RGB 值

How to properly get RGB values from 3 input ranges in HTML page

我目前正在为我的 LED 开发网络界面。所以我想要 3 个滑块,我可以从那里向我的控制器发送一个十六进制值。

这是我目前拥有的:

    <div class="main">
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderRed" style="background: linear-gradient(to right, black 0%, red 70%);">
        </div>
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderGreen" style="background: linear-gradient(to right, black, green 70%);">
        </div>
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderBlue" style="background: linear-gradient(to right, black, blue 70%);">
        </div>
    </div>

和 JS 获取我可以发送到我的控制器的十六进制值:

    sliderRed.oninput = function () {
        var red = sliderRed.value;
        var green = sliderGreen.value;
        var blue = sliderBlue.value;
        color(red, green, blue);
    }
    sliderGreen.oninput = function () {
        var red = sliderRed.value;
        var green = sliderGreen.value;
        var blue = sliderBlue.value;

        color(red, green, blue);
    }
    sliderBlue.oninput = function () {
        var red = sliderRed.value;
        var green = sliderGreen.value;
        var blue = sliderBlue.value;

        color(red, green, blue);
    }

    function color(r, g, b) {
        console.log(rgbToHex(r, g, b));
    }

    function rgbToHex(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
    }

我从上面的代码得到的结果与我想要得到的 #000000#ffffff 之间的值相去甚远。 相反,如果我移动滑块,我会得到像 #86122240 这样的值,即使如果我从我的按钮中输入静态值,函数 color() 确实有效。

输入元素的.value属性总是return一个字符串。
In JavaScript + 可以添加数字,也可以连接字符串。
这就是这部分脚本的问题:

((1 << 24) + (r << 16) + (g << 8) + b)

rgb 是字符串。 移位运算符会将它们转换为实数,因此 (r << 16)(g << 16) 将产生正确的值。
但是还有 b...

如果你尝试"add"两个变量,其中一个是一个字符串,结果也将是一个字符串。

((1 << 24) + (r << 16) + (g << 8) + b)

本质上是:

(<number> + <number> + <number> + <string>)

结尾为:

((<number> + <number> + <number>).toString() + <string>)

让我们添加一些数字(实际上是脚本中的字符串)-> r = g = b = "1":

/*1*/ (("1" << 24) + ("1" << 16) + ("1" << 8) + "1")
/*2*/ (16777216  + 65536       + 256        + "1")
/*3*/ (16843008                             + "1")
/*4*/ ("16843008"                           + "1")
/*5*/ "168430081"

现在让我们用一个片段和您的公式来测试这个假设:

console.log((("1" << 24) + ("1" << 16) + ("1" << 8) + "1").toString(16).slice(1));

tl;dr:
rgb 的值转换为实际数字,然后再将它们用于公式

console.log(((1 << 24) + (1 << 16) + (1 << 8) + 1).toString(16).slice(1));

工作示例:

sliderRed.oninput = function() {
  var red = sliderRed.value;
  var green = sliderGreen.value;
  var blue = sliderBlue.value;
  
  color(red, green, blue);
}
sliderGreen.oninput = function() {
  var red = sliderRed.value;
  var green = sliderGreen.value;
  var blue = sliderBlue.value;

  color(red, green, blue);
}
sliderBlue.oninput = function() {
  var red = sliderRed.value;
  var green = sliderGreen.value;
  var blue = sliderBlue.value;

  color(red, green, blue);
}

function color(r, g, b) {
  r = parseInt(r, 10);
  g = parseInt(g, 10);
  b = parseInt(b, 10);
  
  console.log(rgbToHex(r, g, b));
}

function rgbToHex(r, g, b) {
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
<div class="main">
  <div class="slideContainer">
    <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderRed" style="background: linear-gradient(to right, black 0%, red 70%);">
  </div>
  <div class="slideContainer">
    <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderGreen" style="background: linear-gradient(to right, black, green 70%);">
  </div>
  <div class="slideContainer">
    <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderBlue" style="background: linear-gradient(to right, black, blue 70%);">
  </div>
</div>

您正在尝试将您的 rgb 值作为字符串推送到您的 rgbToHex() 函数。只需先在 color() 函数中使用 parseInt() 函数将它们转换为整数,然后将转换后的 rgb 值发送到 rgbToHex() 函数。

此外,所有三个输入侦听器都在做同样的事情,因此只需创建一个名为 say 的单独函数,assignRGB() 并在调用这三个滑块的输入事件中的任何一个时调用该函数。

您还可以进一步清理代码,方法是使用 querySelectorAll() 方法检索所有三个输入并将输入侦听器添加到每个输入。


检查并运行以下代码片段以获取上述方法的实际示例:

const rgbSliders = document.querySelectorAll('.slider');

function assignRGB() {
    var red = sliderRed.value;
    var green = sliderGreen.value;
    var blue = sliderBlue.value;
    color(red, green, blue);
}

rgbSliders.forEach(function(slider){
  slider.addEventListener('input', assignRGB);
});

function color(r, g, b) {
  const x = parseInt(r);
  const y = parseInt(g);
  const z = parseInt(b);

  console.log(rgbToHex(x,y,z));
}

function rgbToHex(r, g, b) {
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
<div class="main">
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderRed" style="background: linear-gradient(to right, black 0%, red 70%);">
        </div>
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderGreen" style="background: linear-gradient(to right, black, green 70%);">
        </div>
        <div class="slideContainer">
            <input type="range" class="slider" value="0" min="0" max="255" step="1" id="sliderBlue" style="background: linear-gradient(to right, black, blue 70%);">
        </div>
    </div>