简体   繁体   中英

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

I am currently working on a web interface for my LED. So I want to have 3 sliders from where I can sent a hex value to my controller with.

This is what I have so far:

    <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>

and the JS to get the hex value I can send to my controller:

    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);
    }

The result i get from the above code is not anywhere close to the values between #000000 and #ffffff that I want to get. Instead i get values like #86122240 if I move the sliders even though the function color() does work if i put in static values from my buttons.

You are trying to push your rgb values as strings to your rgbToHex() function. Just convert them to integers first in your color() function using the parseInt() function and then send the converted rgb values to your rgbToHex() function.

Also, all three of your input listeners are doing the same thing so just create a separate function called say, assignRGB() and call that function when any of those three sliders' input event is invoked.

You can also further clean up your code by using the querySelectorAll() method to retrieve all three inputs and add the input listener to each one.


Check and run the following Code Snippet for a practical example of the above approach:

 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>

The .value property of an input element will always return a string.
In JavaScript + can add numbers but also concatenate strings.
And that's the problem in this part of your script:

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

r , g , and b are strings. The shift operator will convert them into real numbers, hence (r << 16) and (g << 16) will produce the correct values.
But then there's b ...

If you try to "add" two variables, and one of them is a string, the result will also be a string.

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

is essentially:

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

which will end as:

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

Let's add some numbers (that are actually strings like in your script) -> 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"

Now let's test this assumption with a snippet and your formula:

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

tl;dr :
Convert the values for r , g and b into actual numbers before using them in your formula

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

Working example:

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM