Javascript HTML5画布-在圆上绘制线性渐变(色轮)

Javascript HTML5画布-在圆上绘制线性渐变(色轮),javascript,html5-canvas,linear-gradients,radial-gradients,color-wheel,Javascript,Html5 Canvas,Linear Gradients,Radial Gradients,Color Wheel,我试图画一个圆,不是径向梯度,而是围绕圆的线性梯度。。。基本上,我正在尝试创建一个色轮,它必须是动态的,因为颜色可以自定义。。。然而,我完全困惑于如何处理这件事 我想我可以画我自己的圆并给它上色,然后用一个更大的半径循环这个过程来填充它。但事实证明,这不仅是非常低效的,而且是非常有问题的 这是我的第一次尝试: 我坚持使用这种方法,但改变了它,为圆上的每个点填充一个2x2的正方形。它可以很好地混合3种颜色,但是你开始注意到它的失真 不管怎么说,我一直在继续努力,这就是我现在所拥有的: 我试图实现的

我试图画一个圆,不是径向梯度,而是围绕圆的线性梯度。。。基本上,我正在尝试创建一个色轮,它必须是动态的,因为颜色可以自定义。。。然而,我完全困惑于如何处理这件事

我想我可以画我自己的圆并给它上色,然后用一个更大的半径循环这个过程来填充它。但事实证明,这不仅是非常低效的,而且是非常有问题的

这是我的第一次尝试: 我坚持使用这种方法,但改变了它,为圆上的每个点填充一个2x2的正方形。它可以很好地混合3种颜色,但是你开始注意到它的失真

不管怎么说,我一直在继续努力,这就是我现在所拥有的:

我试图实现的是这样的目标:

“亮度”从白色到黑色的渐变不是问题,因为我知道,在绘制光谱后,可以通过使用径向渐变来实现。不过,如果能帮我弄清楚如何绘制光谱,我将不胜感激

我甚至在想我可以画一个线性的,然后弯曲变换它,但是没有任何本机函数可以做到这一点,并且可以处理一些超出我技能水平的事情-/

看看这个:

例如,可以按如下方式设置渐变停止:

h = 360-(ang-start)/(end-start) * 360;
s = '100%';

grad.addColorStop(0, 'hsl('+[h,s,'0%'].join()+')');  //black 
grad.addColorStop(.5,'hsl('+[h,s,'50%'].join()+')'); //color
grad.addColorStop(1, 'hsl('+[h,s,'100%'].join()+')');//white
看看这个:

例如,可以按如下方式设置渐变停止:

h = 360-(ang-start)/(end-start) * 360;
s = '100%';

grad.addColorStop(0, 'hsl('+[h,s,'0%'].join()+')');  //black 
grad.addColorStop(.5,'hsl('+[h,s,'50%'].join()+')'); //color
grad.addColorStop(1, 'hsl('+[h,s,'100%'].join()+')');//white

我的第一个注意事项是,您链接到的图像包含所有3个组件,它不需要更改,可以只是一个静态图像

我改编了一个项目中的一些代码:


这是按像素进行的,这是精确的,但您可能希望绘制一个轮廓来消除锯齿。它可以调整为使用自定义颜色,而不是插值色调。

我的第一个注意事项是,您链接的图像包含所有3个组件,无需更改,可以只是静态图像

我改编了一个项目中的一些代码:



这是按像素进行的,这是精确的,但您可能希望绘制一个轮廓来消除锯齿。它可以调整为使用自定义颜色,而不是插入色调。

创建类似于链接图像的内容最好是从HSB转换为RGB,我在上发布了一个示例,但正如您所说,您需要自定义颜色,您需要不同的吗?@Kris您应该将其作为一个答案发布,比我的好多了。@Kris哇!这是一些很好的编码。。。不幸的是,由于我的数学能力不足,我很难理解它。有一天,我希望我能创造出这样的东西。谢谢分享!创建像你链接的图像这样的东西最好通过从HSB转换为RGB来完成,我在上发布了一个例子,但正如你所说的,你需要定制颜色吗?你需要一些不同的东西吗?@Kris你应该把它作为一个答案,它比我的好得多。@Kris哇!这是一些很好的编码。。。不幸的是,由于我的数学能力不足,我很难理解它。有一天,我希望我能创造出这样的东西。谢谢分享!哦,有趣的方法!我喜欢!一定要玩一下这个!啊,我不知道hsl,已经重写了你的第一个计算hsv然后转换成rgb。。。但是谢谢你的更新,这是如此简单!只发现一个问题,在//Knockout下圆弧上的位置应为0,0,因为仍在应用ctx.translate。或者,您可以在翻译之前执行ctx.save,然后在/之前执行另一个ctx.restoreKnockout@user1960364实际上,你可以忽略掉淘汰赛。这是我尝试的第一件事的一部分,不再需要了。哦,有趣的方法!我喜欢!一定要玩一下这个!啊,我不知道hsl,已经重写了你的第一个计算hsv然后转换成rgb。。。但是谢谢你的更新,这是如此简单!只发现一个问题,在//Knockout下圆弧上的位置应为0,0,因为仍在应用ctx.translate。或者,您可以在翻译之前执行ctx.save,然后在/之前执行另一个ctx.restoreKnockout@user1960364实际上,你可以忽略掉淘汰赛。这是我尝试的第一件事的一部分,现在已经不需要了。这是解决我问题的另一个很好的方法!数学是高于我的技能水平,但每像素解决方案的简单性是伟大的!再次感谢分享令人惊讶的是,@shmiddy的方法似乎比另一种解决我的问题的方法快了一点!数学是高于我的技能水平,但每像素解决方案的简单性是伟大的!再次感谢分享令人惊讶的是,@shmiddy的速度似乎稍微快一点
step = Math.PI / 360

ctx.fillRect(0, radius - thickness, radius/10, thickness);
h = 360-(ang-start)/(end-start) * 360;
s = '100%';

grad.addColorStop(0, 'hsl('+[h,s,'0%'].join()+')');  //black 
grad.addColorStop(.5,'hsl('+[h,s,'50%'].join()+')'); //color
grad.addColorStop(1, 'hsl('+[h,s,'100%'].join()+')');//white
function drawColourArc(image) {
    var data = image.data;
    var i = 0;
    var w = image.width, h = image.height;
    var result = [0, 0, 0, 1];
    var outer = 1, inner = 0.5;
    var mid = 0.75;

    for (var y = 0; y < h; y++) {
        for (var x = 0; x < w; x++) {

            var dx = (x / w) - 1, dy = (y / w) - 1;

            var angular = ((Math.atan2(dy, dx) + Math.PI) / (2 * Math.PI)) * 4;
            var radius = Math.sqrt((dx * dx) + (dy * dy));

            if (radius < inner || radius > outer) {
                data[i++] = 255;
                data[i++] = 255;
                data[i++] = 255;
                data[i++] = 0;
            }
            else {
                if (radius < mid) {
                    var saturation = 1;
                    var brightness = (radius - 0.5) * 4;
                }
                else {
                    var saturation = 1- ((radius - 0.75) * 4);
                    var brightness = 1;
                }

                result[0] = angular;
                result[1] = saturation;
                result[2] = brightness;

                result[3] = 1;

                //Inline HSBToRGB
                if (result[1] == 0) {
                    result[0] = result[1] = result[2] = result[2];
                }
                else {
                    var varH = result[0] * 6;
                    var varI = Math.floor(varH); //Or ... var_i = floor( var_h )
                    var var1 = result[2] * (1 - result[1]);
                    var var2 = result[2] * (1 - result[1] * (varH - varI));
                    var var3 = result[2] * (1 - result[1] * (1 - (varH - varI)));

                    if (varI == 0 || varI == 6) {
                        result[0] = result[2];
                        result[1] = var3;
                        result[2] = var1;
                    }
                    else if (varI == 1) {
                        result[0] = var2;
                        result[1] = result[2];
                        result[2] = var1;
                    }
                    else if (varI == 2) {
                        result[0] = var1;
                        result[1] = result[2];
                        result[2] = var3;
                    }
                    else if (varI == 3) {
                        result[0] = var1;
                        result[1] = var2;
                        result[2] = result[2];
                    }
                    else if (varI == 4) {
                        result[0] = var3;
                        result[1] = var1;
                        result[2] = result[2];
                    }
                    else {
                        result[0] = result[2];
                        result[1] = var1;
                        result[2] = var2;
                    }

                }
                //End of inline
                data[i++] = result[0] * 255;
                data[i++] = result[1] * 255;
                data[i++] = result[2] * 255;
                data[i++] = result[3] * 255;
            }
        }
    }
};
var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext("2d");
var image = ctx.createImageData(canvas.width, canvas.height);

drawColourArc(image);
ctx.putImageData(image, 0, 0);