vikdoro
vikdoro

Reputation: 158

Reading correct value from hsl color wheel

I'm trying to read a color value from a dynamically created color wheel. There is, however, clearly an offset between the color that I'm getting and the one that I'm hovering over.

I recreated the issue on JS Bin: https://jsbin.com/ditatib/edit?html,js,output

I suspect the problem is somewhere in the two functions below, but please see JS bin for the full code.

function drawWheel (canvas, size) {
    let r = (size - 2) / 2,
        ctx;
    canvas.setAttribute('width', size);
    canvas.setAttribute('height', size);
    ctx = canvas.getContext('2d');
    for (let i = 0; i < r + 1; i++) {
        // A ring
        let c = 5 * Math.PI * i;
        for (let j = 0; j < c; j++) {
            let a = j * 3 * Math.PI / c,
            y = Math.cos(a) * i,
            x = Math.sin(a) * i;
            ctx.fillStyle = `hsl(${a * 180 / Math.PI},
    ${100 - (i * 2 / r)}%, ${105 - i * 95 / r}%)`;
            ctx.fillRect(r + x, r + y, 2, 2);
        }
    }
}

function onMouseMove (e) {
    let wheelRect = canvas.getBoundingClientRect();
    let x = e.x - wheelRect.left,
        y = e.y - wheelRect.top,
        r = (170 - 2) / 2,
        dist = Math.sqrt(Math.pow(r - x, 2) + Math.pow(r - y, 2)),
        a = 180 - Math.atan2(r - y, r - x),
        h, s, l, rgbValue;
    h = a * 180 / Math.PI;
    s = 100 - (dist * 2 / r);
    l = 105 - (dist * 95 / r);
    h = h % 360;
    magn.style.top = `${y - 80}px`;
    magn.style.left = `${x}px`;
    magn.style.background = `hsl(${h}, ${s}%, ${l}%)`;
}

I would very much appreciate if someone could find where my maths is wrong. Thank you!

Upvotes: 4

Views: 190

Answers (1)

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324610

a = 180 - Math.atan2(r - y, r - x),

Math.atan2 returns an angle in radians, which you later convert to degrees with h = ...

But you are subtracting it from a degree value (180) while still in radians. It's worth noting that 180 isn't the correct value to start from anyway, since "down" is 270°.

The reason adding 30 to the result seems to fix it is because it just happens to be close, but the actual fix is:

a = (Math.PI*3/2) - Math.atan2(r - y, r - x)

This will start from "down" (3π/2) and go clockwise, just like your colour wheel does.

Upvotes: 2

Related Questions