首页 > 解决方案 > 制作具有可选梯度问题的 HSL 托盘

问题描述

我正在尝试制作一个颜色托盘,用户可以在其中单击渐变,它会向您显示 RGB 和 HSL 值到目前为止,我已经打印出所有色调值,现在我要做的是进行适当的显示饱和度和亮度/亮度值可以在这里看到https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Colors/Color_picker_tool

我尝试使用双嵌套循环作为生成器,例如:

function * hslGen(hue){  
    for(let s = 0; s < 100; s++){
        for(let l = 100; l > 0; l--){
            yield `hsl(${hue}, ${s}%, ${l}%)`;}
    }
}

但结果看起来如下https://codepen.io/superpauly/pen/XWMQboe?editors=1010我应该使用哪个循环来显示上面示例中所示的颜色托盘?

所以我得到了生成器,其余代码如下:

const canvasContext = canvRef.current.getContext("2d");
    for (let hue = 0; hue < 360; hue++) {
        // Generates Hue Spectrum
        canvasContext.fillStyle = "hsl(" + hue + ", 100%, 50%)";
        canvasContext.fillRect(5 * hue, 0, 5, 75);
    }
    
    canvRef.current.addEventListener("click", (e) => {
        data = canvasContext.getImageData(e.layerX, e.layerY, 1, 1).data;
        color.rgb = `rgb( ${data[0]}, ${data[1]}, ${data[2]})`;
        color.h = rgbToHue(data);
        color.hsl = `hsl( ${color.h}, 100%, 50%)`;

        let pixel = 0;
        for (let m of hslGen(color.h)){
            canvasContext.fillStyle = m; //HSL Generator string
            canvasContext.fillRect(pixel+=1, 75, 1440, 500); // Here is where I try to make the gradient bu it fails.
        }

谢谢你。

标签: javascriptcanvascolors

解决方案


您需要跟踪每个像素的 x 和 y 坐标:

import React, {
    useEffect,
    useRef,
    useState
} from "https://cdn.skypack.dev/react@17.0.1";
import ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";

console.clear();

function * hslGen(hue){

    for(let l = 100; l >= 0; l--)
    {
        for(let s = 0; s <= 100; s++)
        {
            yield `hsl(${hue}, ${s}%, ${l}%)`;
        }
    }
}

const RGBToHex = (r, g, b) => {
    r = r.toString(16);
    g = g.toString(16);
    b = b.toString(16);

    if (r.length == 1) r = "0" + r;
    if (g.length == 1) g = "0" + g;
    if (b.length == 1) b = "0" + b;

    return `#${r+g+b}`;
};

function rgbToHue(getImageData) {
    let rgbHue = {
        red: getImageData[0] / 255,
        green: getImageData[1] / 255,
        blue: getImageData[2] / 255
    };
    let maxValueKey = Object.keys(rgbHue).reduce((a, b) =>
        rgbHue[a] > rgbHue[b] ? a : b
    );
    let maxValue = Math.max(rgbHue["red"], rgbHue["green"], rgbHue["blue"]);
    let minValue = Math.min(rgbHue["red"], rgbHue["green"], rgbHue["blue"]);
    let hue = 0.0;
    switch (maxValueKey) {
        case "red":
            hue = (rgbHue["green"] - rgbHue["blue"]) / (maxValue - minValue);
            break;
        case "green":
            hue = 2.0 + (rgbHue["blue"] - rgbHue["red"]) / (maxValue - minValue);
            break;
        case "blue":
            hue = 4.0 + (rgbHue["red"] - rgbHue["green"]) / (maxValue - minValue);
            break;
    }
    hue = hue * 60.0;
    if (hue < 0.0) {
        hue = hue + 360.0;
    }
    console.log("Hue in Deg: " + hue);
    return hue;
}

const ColorPicker = () => {
    const canvRef = useRef();
    const color = { rgb: "", hsl: "",
                                h:0};
    let [col, setCol] = useState({});
    let data = 0;

    useEffect(() => {
        const canvasContext = canvRef.current.getContext("2d");
        for (let hue = 0; hue < 360; hue++) {
            canvasContext.fillStyle = "hsl(" + hue + ", 100%, 50%)";
            canvasContext.fillRect(5 * hue, 0, 5, 75);
        }
        
        canvRef.current.addEventListener("click", (e) => {
            data = canvasContext.getImageData(e.layerX, e.layerY, 1, 1).data;
            color.rgb = `rgb( ${data[0]}, ${data[1]}, ${data[2]})`;
            color.h = rgbToHue(data);
            color.hsl = `hsl( ${color.h}, 100%, 50%)`;
            setCol({
                rgb: color.rgb,
                hsl: color.hsl
            });
            
            debugger;
            let x = 0,
                    y = 0,
                    pix = 3; //pixel size
            console.log("Start");
            for (let m of hslGen(color.h)){
                canvasContext.fillStyle = m;
                canvasContext.fillRect(100 + x, 175 + y, pix, pix); //Need to made this a 2d saturation, light graph
                console.log(m, x, y);
                x += pix;
                x = x % (pix * 101);
                if (!x)
                    y += pix;


            }
            console.log("End");
            
        });
    
        console.log(color);
    }, []);

    return (
        <>
            <canvas
                ref={canvRef}
                height={window.innerHeight}
                width={window.innerWidth}
            ></canvas>
            <span>HSL: {col.hsl}</span>
            <span>RGB: {col.rgb}</span>
        </>
    );
};

ReactDOM.render(, document.getElementById("colorCanvas"));

https://codepen.io/vanowm/pen/JjWgJOO


推荐阅读