├── 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 | } --------------------------------------------------------------------------------