NIKO'S BLOG

用canvas做一个简易取色器

MDN上学习canvas相关API时,看到有个demo(下图)跟平时用的拾色器有点像。于是我想canvas能不能用来做拾色器呢?仔细想了一下,答案是可以的,并做了一个简单的demo(双击拾色)。在这里把思路简单记录一下。

先看MDN上的例子

直接贴代码

1
2
3
4
5
6
7
8
9
10
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (var i=0;i<6;i++){
for (var j=0;j<6;j++){
ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
Math.floor(255-42.5*j) + ',0)';
ctx.fillRect(j*25,i*25,25,25);
}
}
}}

示例代码用for套for循环定义了6x6共36个小矩形的背景颜色(ctx.fillStyle),并把这些小矩形绘制了出来(ctx.fillRect)。

结合fillRect(x, y, width, height)ctx.fillRect(j*25,i*25,25,25);可以推出:for魂环中的i控制着矩形在y轴方向上的绘制。j控制着巨星在x轴方向上的绘制。这一点很重要,待会往上面示例代码中添加代码会用到(ps:有好的思维导图软件的希望推荐一波,xmind不适合画下面这样的,又不想开ps,所以,我用了画图软件…)。

需求分析

现在要实现拾色器的功能,无非就是点击上面的矩形小色块时,拿到当前点击区域对应的颜色值。再细分一下就是要实现两点功能:

  1. 把每一个小矩形的位置信息和颜色信息保存起来。这一点可以用一个二维数组或者对象数组(姑且这么叫吧)来实现。我是用的后者,因为语义会更清晰一点。
  2. 根据鼠标点击的位置判断出点击区域属于哪个矩形,并从上面保存的二维数组/对象数组中取出相应的颜色值。

开始实现

实现第一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 初始化一个数组用来保存小矩形的位置信息和颜色信息
var arr = [];
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (var i=0;i<6;i++){
for (var j=0;j<6;j++){
ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
Math.floor(255-42.5*j) + ',0)';
ctx.fillRect(j*25,i*25,25,25);
// 每绘制一个矩形就保存起来
arr.push({
x1: 25 * j, // 矩形的左上角x坐标
y1: 25 * i, // 矩形的左上角y坐标
x2: 25 * j + 25, // 矩形的右下角x坐标
y2: 25 * i + 25, // 矩形的右下角y坐标
// 矩形的颜色
color: 'rgb(' + Math.floor(255 - 42.5 * i) + ',' + Math.floor(255 - 42.5 * j) + ',0)'
});
}
}
}}

这样每一个矩形的位置信息和颜色信息都被包装成一个对象,并被推送到数组中了。第一点完成。

实现第二点

鼠标的位置信息可以在鼠标事件对象MouseEvent上拿到,分别为e.clientXe.clientY

1
2
3
4
5
6
7
8
9
10
11
12
13
canvas.addEventListener('dblclick', function (e) {
var x = e.clientX;
var y = e.clientY;
for (var i = 0; i < arr.length; i++) {
if (x >= arr[i].x1
&& x < arr[i].x2
&& y >= arr[i].y1
&& y < arr[i].y2) {
// 拿到颜色啦
console.log(arr[i].color);
}
}
}, true);

为了简化计算,我设置了body {margin: 0;},实际的情况可能不会有这么理想。

完整代码里有对rgb颜色值和十六进制颜色值之间转换的处理。

结语

以上只是简单记录一下拾色器实现的思路,真正的拾色器远不止这么一点颜色,而且颜色都是渐变过度的,更细粒化,这样选取范围的判断应该要复杂一点。后续如果有整理的话会再更新。

笔者注

博客内文章若不另外注明,均为原创。转载请注明出处,谢谢。

博客内容主要是对新知识的归纳、总结。记录博客的目的也是为了方便自己日后的巩固复习。欢迎大家提出文章中理解错误的地方,不胜感激。若文章对你有帮助,将是我的荣幸。