上周去菜市场买菜,看到路边一个二维码,于是想起阿里巴巴,接着想起之前上班都会路过阿里巴巴,接着想起马云,然后想到马赛克!!!于是我回家了,想学习下前端中的马赛克.

完成的功能

  • 选择当地一张图片
  • 点击绘制马赛克
  • 拖动绘制马赛克

为了方便,相关js代码直接写在了index.html中,大致分为加载图片,添加监听,方法触发,绘制小方块(马赛克),计算颜色,数组升维这几个方法,UI部分通过canvas 标签和input 标签绘制.
下面是完整的index.html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!doctype html>
<html>

<head>
<title></title>
<meta charset="UTF-8">
<meta name="Keywords" content="马赛克 canvas">
<meta name="Description" content="学习前端马赛克">
</head>
<style>
canvas {
border: 1px black solid;

}
</style>

<body>
<div id="mask">
<canvas width="600" height="600">
</canvas>
<input type="file" class='input'>
</div>
<script>
var canvas = document.querySelector('canvas');
var input = document.querySelector('#mask .input');
var ctx = canvas.getContext('2d');
var mousedown = false;
var t = 15;
input.onchange = function () {
loadimg();
}
/**
*加载图片
*/
function loadimg() {
var img = new Image();
img.src = window.URL.createObjectURL(input.files[0]);
img.onload = function () {
ctx.drawImage(img, 0, 0, 600, 600);
}
register();
}
/**
*添加监听
*/
function register() {
canvas.addEventListener('mousedown', action)
canvas.addEventListener('mousemove', action)
canvas.addEventListener('mouseup', action)
}
/**
*方法触发
*/
function action(e) {
var dx = parseInt(((e.offsetX - t / 2) / t) * t)
var dy = parseInt(((e.offsetY - t / 2) / t) * t)
if (e.type == "mousedown") {
mousedown = true;
computeColor(dx, dy);
}
if (mousedown && e.type == "mousemove") {
computeColor(dx, dy);
}
if (e.type == "mouseup") {
mousedown = false;
}
}

/*
* 画小方块
*/
function rect(x, y, c) {
ctx.beginPath();
ctx.fillStyle = c;
var dx = parseInt(x / t)*t,dy = parseInt(y / t)*t
ctx.rect(dx, dy, t, t);
ctx.fill();
}
/**
计算颜色
*/
function computeColor(x, y) {
var arrList = restore(ctx.getImageData(x,y,t,t).data,4); //一维数组
var vr = 0, vg = 0, vb = 0,al = arrList.length;
for(var i = 0; i < al; i++){
vr += arrList[i][0];
vg += arrList[i][1];
vb += arrList[i][2];
var color = 'rgb(' + Math.floor(vr/al) + ',' + Math.floor(vg/al) + ',' + Math.floor(vb/al) + ')';
rect(x,y,color);
}
}
/**
*数组升维 [1,2,3,4] => [[1,2],[3,4]]
*/
function restore(arr, step) {
var list = [];
var index = 0;
var n = Math.floor(arr.length/step);
for(var i = 0; i < n ;i++){
list.push(arr.slice(index,index+step));
index += step;
}
return list;
}
</script>
</body>

</html>

效果图:

马赛克原图 马赛克效果

源码