LWDW!

Learn the work from doing the work🍺

俺的colorPicker制作思路
Posted on 2017-04-09

原任务地址

说实话,一开始看到这个任务内心是相当懵比的——主要就是有两个点一下子没有头绪,但说实话,只要get到这两点的思路,这个任务也就完成了一半了。接下来俺就具体展开一下:

1. 如何渲染颜色选取面板

讲道理我不知道为什么前端技术学院给了这么个示意图,因为这个图根本就取不到所有颜色啊喂!

任务图

为什么呢,颜色通常都是由三种成分(so我们最后确定颜色其实就是用三个变量)定义的,因此在我们通常用三维空间来描述颜色模型,RGB,HSL,以及此次任务中我用到的HSV都是这样,弄清楚颜色模型,也就知道该用什么方法来渲染了,下文将详细阐释:

RGB(参考维基词条:三原色光模式

当前表示RGB的主流方法是用三个0-255间的整数,相信大家都知道,那么用脚趾头都能想出来,RGB的颜色模型是一个方块儿,这张图可以很直接的看出来。

RGB色彩模型

那么我们要用RGB颜色模型作为渲染标准么,我个人觉得不太靠谱,这个任务给出的示例图的选择器由两部分组成,一个长长的颜色条,和以这个颜色条的某个颜色(也就是我们的第一个变量)为标准渲染出的颜色面板(这个面板的上某点的横纵坐标正好是第二,第三个变量,也就确定了唯一的颜色)。那么以我小学水平的数学水平,我的第一反应就是以x,y,z的某个轴为颜色条,把这个方块儿切片儿,那不就成了么!然而切开来一看俺就傻逼了,这里面花花绿绿的我压根不知道咋渲染啊!所以,RGB被我pass掉了。

切面

HSL与HSV(参考维基词条:HSL和HSV的色彩空间

HSL和HSV是将RGB色彩模型中的点在圆柱坐标系中的表示法,H一般用0-360之间的整数,代表圆柱的一周的角度,S和L/V是0-1之间的小数或对应的百分数(一般取到两位即可满足人眼的需要),也就是说,他们的模型是一个圆柱体。HSL即色相饱和度亮度,而HSV指色相饱和度明度。但是,你说这个谁懂啊!还是看图直接。

HSL和HSV

比较一番之后,咱们就发现这个圆柱体相当适合切片儿——以圆柱的轴进行360度切片儿,切出来的截面非常好渲染,基本就是主色向着白色和黑色进行过渡,大家肯定都用过各种colorPicker工具,看这个截面应该会觉得很熟悉吧。那么再看一眼360度的颜色条,这个其实HSL和HSV都是可以的,如果是HSL要取S为1,L为0.5的环,HSV要取S为1,V为1的环,分别对应两种色彩模型最明艳的环。我个人选择了HSV作为取色标准,因为谷歌的colorPicker工具和sublime的colorPicker工具都采用的是这种,但HSV本身不在CSS规定中(HSL在CSS3标准中,可在代码里直接使用),所以在展现时要做转换。

具体渲染

渲染其实很简单,canvas和CSS都支持渐变渲染,只不过要渲染两层才能达到截面的效果,竖着渲染一层 透明——>黑 ,再横着渲染 白——>颜色条选取色 。具体见代码:

let colorPanel = (function() {
    let canvas = document.getElementById('panel');
    let ctx = canvas.getContext('2d');

    let lightGradient = ctx.createLinearGradient(0, 0, 0, 400); // 亮度渲染

    lightGradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
    lightGradient.addColorStop(1, 'rgba(0, 0, 0, 1)');

    return {
        render: function(color) { // 需要渲染两次
            ctx.clearRect(0, 0, 400, 400) // 清除画布

            let colorGradient = ctx.createLinearGradient(0, 0, 400, 0); // 颜色渲染

            colorGradient.addColorStop(0, 'rgb(255, 255, 255)');
            colorGradient.addColorStop(1, color);

            ctx.fillStyle = colorGradient;
            ctx.fillRect(0, 0, 400, 400);

            ctx.fillStyle = lightGradient;
            ctx.fillRect(0, 0, 400, 400);
        }
    }
})();

相对的,颜色条其实就是将360度的色带剪开拉直了,因为色带不需要改变,所以渲染时利用CSS的渐变便可,注意颜色要首尾相接。

顺带提一下为啥前文说这次任务给的示例图不靠谱,因为示例图的渲染只需要一次啊,以此作为标准,不管怎么选取都相当于只改变一个变量(以HSL来讲,S会固定为1),加上色带的改变,总共就只改变两个变量,当然不能选取到所有颜色。

2. 如何取色

其实在确定了渲染逻辑后,取色逻辑相应的就确定了,在我以HSV作为渲染模型后,取色逻辑便是——色带是竖着的,那么就以点击色带的纵坐标,代表H,取值范围0-360;取色板主体是个方块儿,则以取色点的横纵坐标代表S和V,取值范围0-1。不行就看看谷歌的colorPicker的变化规律,相当好懂。这样取色就唯一确定了,接下来只要按照公式HSV值转换成RGB和HSL值即可,在改变RGB和HSL时,也同样的先转换为HSV再进行选取。


这个任务的难点也就是这样吧,在学习过程中有很多个人的情感化理解,表述出来总感觉太过口语化,很可能有许多不严谨甚至错误的观点,欢迎各位指出。总之希望能提供一种思路,也希望看到更多新的思路。