├── .gitignore ├── LICENSE ├── README.md ├── dist └── pixel.js ├── gulpfile.js ├── index.html ├── js └── pixel.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ahmet Simsek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pixel-animator 2 | 3 | ######[demo](https://jsfiddle.net/indatawetrust/2zsqmfab/15/) 4 | 5 | ####npm install -g http-server 6 | 7 | ####http-server 8 | 9 | ~color selector added 10 | 11 | ~frame timer added 12 | 13 |  14 | 15 | -------------------------------------------------------------------------------- /dist/pixel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var canvas = document.querySelector('#frame'), 4 | colorSelector = document.querySelector('#colors'), 5 | time = document.querySelector('input'), 6 | span = document.querySelector('span'), 7 | c = canvas.getContext('2d'), 8 | _c = colorSelector.getContext('2d'), 9 | add = document.querySelector('#add'), 10 | remove = document.querySelector('#remove'), 11 | reset = document.querySelector('#reset'), 12 | start = document.querySelector('#start'), 13 | colors = ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6', '#34495e', '#f1c40f', '#e67e22', '#e74c3c', '#95a5a6', '#bdc3c7']; 14 | 15 | var interval = null, 16 | frames = [], 17 | isdown = false, 18 | list = [], 19 | selectColor = colors[0]; 20 | 21 | var draw = function draw(maps, opacity) { 22 | c.clearRect(0, 0, 200, 200); 23 | 24 | maps.forEach(function (map, i) { 25 | map.forEach(function (_, j) { 26 | if (maps[i][j].select) { 27 | c.save(); 28 | c.beginPath(); 29 | c.globalAlpha = opacity; 30 | c.fillStyle = maps[i][j].color; 31 | c.fillRect(i * 20, j * 20, 20, 20); 32 | c.closePath(); 33 | c.restore(); 34 | } 35 | 36 | c.strokeRect(i * 20, j * 20, 20, 20); 37 | }); 38 | }); 39 | }; 40 | 41 | // color selector 42 | colors.forEach(function (color, i) { 43 | _c.fillStyle = color; 44 | _c.fillRect(i * 20, 0, 20, 20); 45 | }); 46 | 47 | colorSelector.addEventListener('mousedown', function (e) { 48 | _c.clearRect(0, 0, 200, 20); 49 | 50 | colors.forEach(function (color, i) { 51 | _c.fillStyle = color; 52 | _c.fillRect(i * 20, 0, 20, 20); 53 | }); 54 | 55 | var x = e.clientX - 8, 56 | dx = -1; 57 | 58 | while (x > 0) { 59 | x -= 20; 60 | dx++; 61 | } 62 | _c.lineWidth = 4; 63 | _c.strokeRect(dx * 20, 0, 20, 20); 64 | selectColor = colors[dx]; 65 | }); 66 | 67 | // frame create 68 | var frame = function frame() { 69 | var maps = []; 70 | 71 | for (var i = 0; i < 10; i++) { 72 | var _ = []; 73 | for (var j = 0; j < 10; j++) { 74 | _.push({ 75 | select: 0, 76 | color: '#fff', 77 | opacity: 1 78 | }); 79 | } 80 | maps.push(_); 81 | } 82 | 83 | return maps; 84 | }; 85 | 86 | frames.push(frame()); 87 | 88 | draw(frames[0]); 89 | 90 | canvas.addEventListener('mousedown', function (e) { 91 | isdown = true; 92 | 93 | var x = e.clientX - 8; 94 | var y = e.clientY - 8; 95 | var dx = -1;var dy = -1; 96 | while (x > 0) { 97 | x -= 20; 98 | dx++; 99 | } 100 | while (y > 0) { 101 | y -= 20; 102 | dy++; 103 | } 104 | 105 | if (list.indexOf(dx + '' + dy) == -1) { 106 | frames[frames.length - 1][dx][dy].select = !frames[frames.length - 1][dx][dy].select; 107 | frames[frames.length - 1][dx][dy].color = selectColor; 108 | 109 | draw(frames[frames.length - 1], 1); 110 | list.push(dx + '' + dy); 111 | } 112 | }); 113 | 114 | canvas.addEventListener('mousemove', function (e) { 115 | if (isdown) { 116 | var x = e.clientX - 8; 117 | var y = e.clientY - 8; 118 | var dx = -1;var dy = -1; 119 | while (x > 0) { 120 | x -= 20; 121 | dx++; 122 | } 123 | while (y > 0) { 124 | y -= 20; 125 | dy++; 126 | } 127 | 128 | if (list.indexOf(dx + '' + dy) == -1) { 129 | frames[frames.length - 1][dx][dy].select = !frames[frames.length - 1][dx][dy].select; 130 | frames[frames.length - 1][dx][dy].color = selectColor; 131 | 132 | draw(frames[frames.length - 1], 1); 133 | list.push(dx + '' + dy); 134 | } 135 | } 136 | }); 137 | 138 | canvas.addEventListener('mouseup', function (e) { 139 | isdown = false; 140 | list = []; 141 | }); 142 | 143 | canvas.addEventListener('mouseout', function (e) { 144 | isdown = false; 145 | list = []; 146 | }); 147 | 148 | // add frame 149 | add.addEventListener('click', function () { 150 | frames.push(frame()); 151 | draw(frames[frames.length - 2], 0.5); 152 | }); 153 | 154 | // remove frame 155 | remove.addEventListener('click', function () { 156 | clearInterval(interval); 157 | frames.pop(); 158 | 159 | if (frames.length) { 160 | draw(frames[frames.length - 1], 1); 161 | } else { 162 | frames.push(frame()); 163 | draw(frames[0]); 164 | } 165 | 166 | interval = null; 167 | }); 168 | 169 | // start animation 170 | start.addEventListener('click', function () { 171 | var i = -1; 172 | 173 | interval = setInterval(function () { 174 | if (frames.length - 1 == i++) i = 0; 175 | draw(frames[i], 1); 176 | }, time.value); 177 | 178 | start.setAttribute('disabled', 1); 179 | }); 180 | 181 | // reset animation 182 | reset.addEventListener('click', function () { 183 | start.removeAttribute('disabled'); 184 | 185 | clearInterval(interval); 186 | frames = []; 187 | frames.push(frame()); 188 | draw(frames[0]); 189 | interval = null; 190 | }); 191 | 192 | // frame time change 193 | time.addEventListener('mouseup', function (e) { 194 | span.innerText = time.value + ' ms'; 195 | 196 | if (interval != null) { 197 | (function () { 198 | clearInterval(interval); 199 | 200 | var i = -1; 201 | 202 | interval = setInterval(function () { 203 | if (frames.length - 1 == i++) i = 0; 204 | draw(frames[i], 1); 205 | }, time.value); 206 | })(); 207 | } 208 | }); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const babel = require('gulp-babel'); 3 | 4 | gulp.task('default', () => 5 | gulp.src('js/pixel.js') 6 | .pipe(babel({ 7 | presets: ['es2015'] 8 | })) 9 | .pipe(gulp.dest('dist')) 10 | ); 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |