├── README.md
├── index.html
├── sample.jpg
└── src
└── app.js
/README.md:
--------------------------------------------------------------------------------
1 | # 涂鸦生成器
2 |
3 | ## 使用方法
4 | * 替换目录中的sample.jpg文件,打开index.html。
5 | * 将涂鸦到一半的文件保存到sample.jpg旁边,改名为result.jpg,打开index.html。
6 |
7 | ## 环境
8 | 推荐使用火狐浏览器,其他浏览器没有测试过。
9 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/sample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huoshizhe/GraffitiCreater/8315271d88de00a5473da3c95ff24a026dc95121/sample.jpg
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | var widths = [10, Math.random() * 25 + 10, Math.random() * 50 + 10, 60];
2 |
3 | function onPageLoaded() {
4 | loadMonaLisa();
5 | start();
6 | }
7 |
8 | function start() {
9 | setInterval(function() {
10 | step();
11 | }, 5);
12 | }
13 |
14 | var blink = true;
15 |
16 | function clickBtn() {
17 | blink = !blink;
18 | }
19 |
20 | var stepIdx = 0;
21 |
22 | function step() {
23 | if (blink) {
24 | if (stepIdx == 0) {
25 | var canvas = document.getElementById("myCanvas");
26 | var cxt = canvas.getContext("2d");
27 | cxt.lineCap = "round";
28 | drawALine(canvas, cxt, widths);
29 | drawALine(canvas, cxt, widths);
30 | stepIdx = 1;
31 | } else {
32 | copyImg(compare());
33 | stepIdx = 0;
34 | }
35 | } else {
36 | var canvas = document.getElementById("myCanvas");
37 | var cxt = canvas.getContext("2d");
38 | cxt.lineCap = "round";
39 | drawALine(canvas, cxt, widths);
40 | copyImg(compare());
41 | drawALine(canvas, cxt, widths);
42 | copyImg(compare());
43 | }
44 | }
45 |
46 | var colors = [];
47 |
48 | function loadSample() {
49 | var c = document.getElementById("sampleImg");
50 | var myCanvas = document.getElementById("myCanvas");
51 | var cxt = c.getContext("2d");
52 | var img = new Image();
53 | img.onload = function() {
54 | c.width = img.width;
55 | c.height = img.height;
56 | myCanvas.width = img.width;
57 | myCanvas.height = img.height;
58 | cxt.drawImage(img, 0, 0);
59 |
60 | // var data = cxt.getImageData(0, 0, c.width, c.height).data;
61 | // for (var i = 0; i < data.length; i += 4) {
62 | // colors.push('#' + data[i + 0].toString(16) + data[i + 1].toString(16) + data[i + 2].toString());
63 | // }
64 | // colors.push('#000000');
65 | // colors.push('#FF0000');
66 | // colors.push('#00FF00');
67 | // colors.push('#0000FF');
68 | // colors.push('#FFFFFF');
69 |
70 | // console.log(colors.length);
71 | };
72 | img.src = "sample.jpg";
73 | }
74 |
75 | function loadResult() {
76 | var c = document.getElementById("myCanvas");
77 | var cxt = c.getContext("2d");
78 | var img = new Image();
79 | img.onload = function() {
80 | cxt.drawImage(img, 0, 0);
81 | };
82 | img.src = "result.jpg";
83 | }
84 |
85 | function loadMonaLisa() {
86 | loadSample();
87 | loadResult();
88 | }
89 |
90 | var backUpImgData = null;
91 |
92 | function compare() {
93 | if (!backUpImgData) {
94 | return true;
95 | }
96 |
97 | var sampleCanvas = document.getElementById("sampleImg");
98 | var sampleCxt = sampleCanvas.getContext("2d");
99 | var sampleData = sampleCxt.getImageData(0, 0, sampleCanvas.width, sampleCanvas.height).data;
100 |
101 | var canvas = document.getElementById("myCanvas");
102 | var cxt = canvas.getContext("2d");
103 | var data = cxt.getImageData(0, 0, canvas.width, canvas.height).data;
104 |
105 | var backupData = backUpImgData.data;
106 |
107 | var score = 0;
108 | var backupScore = 0;
109 |
110 | for (var i = 0; i < sampleData.length; i++) {
111 | score += Math.max(sampleData[i] - data[i], data[i] - sampleData[i]);
112 | backupScore += Math.max(sampleData[i] - backupData[i], backupData[i] - sampleData[i]);
113 | }
114 |
115 | // console.log('score = ' + score + ', backupScore = ' + backupScore);
116 |
117 | var label = document.getElementById("label");
118 | label.innerHTML = Math.floor(backupScore / sampleData.length * 1000) / 1000;
119 |
120 | return score < backupScore;
121 | }
122 |
123 | function copyImg(right) {
124 |
125 | var canvas = document.getElementById("myCanvas");
126 | var cxt = canvas.getContext("2d");
127 |
128 | if (!backUpImgData) {
129 | backUpImgData = cxt.getImageData(0, 0, canvas.width, canvas.height);
130 | }
131 |
132 | if (right) {
133 | backUpImgData = cxt.getImageData(0, 0, canvas.width, canvas.height);
134 | } else {
135 | cxt.putImageData(backUpImgData, 0, 0);
136 | }
137 | }
138 |
139 | function drawALine(canvas, cxt, widths) {
140 |
141 | // cxt.strokeStyle = '#' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16);
142 | // cxt.strokeStyle = '#' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16) + 'FF';
143 | var colors = [];
144 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16));
145 | colors.push('#' + 'FF' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16));
146 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + 'FF' + Math.floor(Math.random() * 256).toString(16));
147 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16) + 'FF');
148 | colors.push('#' + '00' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16));
149 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + '00' + Math.floor(Math.random() * 256).toString(16));
150 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + Math.floor(Math.random() * 256).toString(16) + '00');
151 | colors.push('#' + '00' + Math.floor(Math.random() * 256).toString(16) + '00');
152 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + '00' + '00');
153 | colors.push('#' + '00' + '00' + Math.floor(Math.random() * 256).toString(16));
154 | colors.push('#' + 'FF' + Math.floor(Math.random() * 256).toString(16) + 'FF');
155 | colors.push('#' + Math.floor(Math.random() * 256).toString(16) + 'FF' + 'FF');
156 | colors.push('#' + 'FF' + 'FF' + Math.floor(Math.random() * 256).toString(16));
157 |
158 | cxt.strokeStyle = colors[Math.floor(Math.random() * colors.length)];
159 |
160 | var areas = [
161 | [0, 0, 1, 1],
162 | [0, 0, 0.5, 0.5],
163 | [0, 0.5, 0.5, 1],
164 | [0.5, 0, 1, 0.5],
165 | [0.5, 0.5, 1, 1],
166 | [0, 0, 0.33, 0.33],
167 | [0.33, 0.33, 0.66, 0.66],
168 | [0.66, 0.66, 1, 1],
169 | [0, 0, 0.33, 0.33],
170 | [0.33, 0.33, 0.66, 0.66],
171 | [0.66, 0.66, 1, 1],
172 | [0, 0, 0.33, 0.33],
173 | [0.33, 0.33, 0.66, 0.66],
174 | [0.66, 0.66, 1, 1],
175 | ];
176 |
177 | var area = areas[Math.floor(Math.random() * areas.length)];
178 |
179 | cxt.lineWidth = widths[Math.floor(Math.random() * widths.length)];
180 | var pos1 = {
181 | x: canvas.width * area[0] + area[2] * Math.random() * canvas.width,
182 | y: canvas.height * area[1] + area[3] * Math.random() * canvas.height
183 | }
184 | var pos2 = {
185 | x: canvas.width * area[0] + area[2] * Math.random() * canvas.width,
186 | y: canvas.height * area[1] + area[3] * Math.random() * canvas.height
187 | }
188 | var controlPos1 = {
189 | x: canvas.width * area[0] + area[2] * Math.random() * canvas.width,
190 | y: canvas.height * area[1] + area[3] * Math.random() * canvas.height
191 | }
192 | var controlPos2 = {
193 | x: canvas.width * area[0] + area[2] * Math.random() * canvas.width,
194 | y: canvas.height * area[1] + area[3] * Math.random() * canvas.height
195 | }
196 | cxt.beginPath();
197 | cxt.moveTo(pos1.x, pos1.y);
198 | cxt.quadraticCurveTo(
199 | controlPos1.x,
200 | controlPos1.y,
201 | controlPos2.x,
202 | controlPos2.y,
203 | pos2.x,
204 | pos2.y
205 | );
206 | cxt.stroke();
207 | }
--------------------------------------------------------------------------------