├── .eslintignore
├── .eslintrc
├── .gitignore
├── .jshintrc
├── .stylelintrc
├── README.md
├── assets
├── css
│ ├── style.css
│ ├── styles.css
│ └── styles.min.css
└── js
│ └── script.js
├── gulpfile.js
├── index.html
├── package-lock.json
├── package.json
└── src
├── js
└── script.js
└── scss
├── reset.scss
└── styles.scss
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build
2 | /assets
3 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "yandex",
3 | "env": {
4 | "browser": true,
5 | "node": true
6 | },
7 | "parser": "babel-eslint",
8 | "rules": {
9 | "quotes": [2, "single"],
10 | "strict": [2, "never"],
11 | "indent": ["error", 2]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .sass-cache
3 | _temp
4 |
5 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "boss": true,
3 | "node": true,
4 | "eqeqeq": true,
5 | "strict": false,
6 | "newcap": false,
7 | "undef": true,
8 | "unused": true,
9 | "onecase": true,
10 | "lastsemic": true
11 | }
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard",
3 | "rules": {
4 | "indentation": 2,
5 | "string-quotes": "double",
6 | "no-duplicate-selectors": true,
7 | "color-hex-case": "upper",
8 | "color-hex-length": "short",
9 | "selector-max-id": 0,
10 | "selector-combinator-space-after": "always",
11 | "selector-attribute-quotes": "always",
12 | "selector-type-case": "upper",
13 | "declaration-block-trailing-semicolon": "always",
14 | "declaration-no-important": true,
15 | "declaration-colon-space-before": "never",
16 | "declaration-colon-space-after": "always",
17 | "property-no-vendor-prefix": true,
18 | "value-no-vendor-prefix": true,
19 | "number-leading-zero": "never",
20 | "function-url-quotes": "always",
21 | "font-family-name-quotes": "always-where-required",
22 | "comment-whitespace-inside": "always",
23 | "comment-empty-line-before": "never",
24 | "at-rule-no-vendor-prefix": true,
25 | "selector-pseudo-element-colon-notation": "double",
26 | "selector-pseudo-class-parentheses-space-inside": "never",
27 | "selector-no-vendor-prefix": true,
28 | "media-feature-range-operator-space-before": "always",
29 | "media-feature-range-operator-space-after": "always",
30 | "media-feature-parentheses-space-inside": "never",
31 | "media-feature-colon-space-before": "never",
32 | "media-feature-colon-space-after": "always"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ShadowPainter
2 | =============
3 |
4 | Js-creator of box-shadow animation. Just for fun : )
5 |
6 | Play with it yoksel.github.io/shadowPainter/
7 |
--------------------------------------------------------------------------------
/assets/css/style.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h2, h3, h4, h5, h6,
2 | p, a, img, b, i, dl, dt, dd, ol, ul, li,
3 | label, article, aside, footer, header, section {
4 | margin: 0;
5 | padding: 0;
6 | border: 0;
7 | font-size: 100%;
8 | font: inherit;
9 | vertical-align: baseline;
10 | }
11 |
12 | body {
13 | line-height: 1;
14 | }
15 |
16 | ol, ul {
17 | list-style: none;
18 | }
19 |
20 | * {
21 | -webkit-box-sizing: border-box;
22 | -moz-box-sizing: border-box;
23 | box-sizing: border-box;
24 | }
25 |
26 | BODY {
27 | background: #FFF;
28 | font: 14px/1.4 'Trebuchet MS', Verdana, sans-serif;
29 | color: #333;
30 | }
31 |
32 | LABEL {
33 | cursor: pointer;
34 | }
35 |
36 | .l-wrapper {
37 | position: absolute;
38 | display: inline-block;
39 | margin: auto;
40 | left: 1em;
41 | right: 1em;
42 | top: 1em;
43 | bottom: 1em;
44 | border: 1px solid #CCC;
45 | white-space: nowrap;
46 | }
47 | .l-wrapper:after {
48 | content: '';
49 | display: table;
50 | width: 100%;
51 | clear: both;
52 | }
53 |
54 | .b-boxes {
55 | position: relative;
56 | text-align: center;
57 | border: 1px solid #CCC;
58 | border-width: 1px 0;
59 | }
60 |
61 | .l-zero-gravity {
62 | position: absolute;
63 | width: 100%;
64 | top: 0;
65 | bottom: 0;
66 | right: 0;
67 | left: 0;
68 | margin: auto;
69 | }
70 |
71 | .b-box {
72 | position: relative;
73 | display: inline-block;
74 | border: 1px solid #CCC;
75 | }
76 | .b-box:nth-of-type(1) {
77 | margin-right: 20px;
78 | }
79 |
80 | .b-panel {
81 | padding: 10px;
82 | color: #888;
83 | }
84 | .b-panel:before, .b-panel:after {
85 | content: '';
86 | display: table;
87 | width: 100%;
88 | clear: both;
89 | }
90 |
91 | .b-title {
92 | display: inline-block;
93 | padding-right: 10px;
94 | line-height: 30px;
95 | }
96 |
97 | .b-steps .b-title {
98 | float: none;
99 | display: inline-block;
100 | margin: 0 auto;
101 | padding: 0;
102 | }
103 |
104 | /* Paint Box
105 | ----------------------------- */
106 | .b-box--paint {
107 | overflow: hidden;
108 | border-width: 0 1px 1px 0;
109 | background-image: -webkit-gradient(linear, left top, right top, from(#CCC), to(transparent)), -webkit-gradient(linear, left top, left bottom, from(#CCC), to(transparent));
110 | background-image: -webkit-linear-gradient(left, #CCC 1px, transparent 1px), -webkit-linear-gradient(top, #CCC 1px, transparent 1px);
111 | background-image: linear-gradient(to right, #CCC 1px, transparent 1px), linear-gradient(to bottom, #CCC 1px, transparent 1px);
112 | background-position: 0 0;
113 | }
114 |
115 | /* Labels
116 | ----------------------------- */
117 | .cell {
118 | display: block;
119 | float: left;
120 | }
121 |
122 | .cell__inp {
123 | position: absolute;
124 | display: none;
125 | }
126 |
127 | .cell__lbl {
128 | display: block;
129 | border-radius: 0;
130 | /*box-shadow: 0 0 2px #999 inset;*/
131 | }
132 |
133 | :checked + .cell__lbl {
134 | position: relative;
135 | }
136 |
137 | .is-colored {
138 | background: orange;
139 | }
140 |
141 | /* Result Box
142 | ----------------------------- */
143 | .b-box--result {
144 | overflow: hidden;
145 | }
146 |
147 | /* Dotts
148 | ----------------------------- */
149 | .dot {
150 | display: block;
151 | position: absolute;
152 | border-radius: 0;
153 | }
154 |
155 | .dot--previous {
156 | opacity: .2;
157 | }
158 |
159 | @-webkit-keyframes shadows {}
160 | /* Palette
161 | ----------------------------- */
162 | .b-palette {
163 | display: inline-block;
164 | }
165 |
166 | .items--colors {
167 | display: inline-block;
168 | vertical-align: middle;
169 | }
170 |
171 | .color {
172 | display: inline-block;
173 | width: 30px;
174 | height: 30px;
175 | }
176 |
177 | .color__inp {
178 | display: none;
179 | }
180 |
181 | .color__lbl {
182 | display: block;
183 | height: 30px;
184 | }
185 |
186 | :checked + .color__lbl {
187 | position: relative;
188 | z-index: 1;
189 | -webkit-box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
190 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
191 | }
192 |
193 | /* Color Controls
194 | ----------------------------- */
195 | .items--colors-controls {
196 | display: inline-block;
197 | position: relative;
198 | height: 30px;
199 | margin-left: 5px;
200 | vertical-align: middle;
201 | }
202 |
203 | .colors-controls__item {
204 | position: absolute;
205 | border: 10px solid transparent;
206 | border-color: #a0a0a0 transparent;
207 | border-width: 10px 4px;
208 | cursor: pointer;
209 | }
210 | .colors-controls__item:hover {
211 | border-color: #878787 transparent;
212 | }
213 | .colors-controls__item:active {
214 | border-color: #545454 transparent;
215 | }
216 |
217 | .colors-controls__item--up {
218 | top: 0;
219 | border-top: 0;
220 | }
221 | .colors-controls__item--up:active {
222 | top: 2px;
223 | }
224 |
225 | .colors-controls__item--down {
226 | bottom: 0;
227 | border-bottom: 0;
228 | }
229 | .colors-controls__item--down:active {
230 | bottom: -2px;
231 | }
232 |
233 | /* Panel
234 | ----------------------------- */
235 | .b-panel {
236 | position: relative;
237 | }
238 |
239 | .b-panel__item {
240 | float: left;
241 | margin-left: 32px;
242 | }
243 | .b-panel__item:first-child {
244 | margin-left: 0;
245 | }
246 |
247 | .text--value {
248 | width: 3.5em;
249 | height: 30px;
250 | line-height: 30px;
251 | pading: 0;
252 | border: 1px solid #CCC;
253 | border-radius: 5px;
254 | text-align: center;
255 | }
256 |
257 | /* Steps
258 | ----------------------------- */
259 | .b-steps {
260 | text-align: center;
261 | -webkit-user-select: none;
262 | -moz-user-select: none;
263 | -ms-user-select: none;
264 | user-select: none;
265 | }
266 |
267 | .steps-control {
268 | display: inline-block;
269 | position: relative;
270 | width: 24px;
271 | height: 24px;
272 | line-height: 24px;
273 | margin: 0 6px;
274 | top: 0;
275 | background: lightgray;
276 | font-weight: bold;
277 | color: #444;
278 | cursor: pointer;
279 | -webkit-transition: all .1s;
280 | transition: all .2s;
281 | }
282 |
283 | .steps-control:hover {
284 | top: -1px;
285 | background: #f2f2f2;
286 | color: #555;
287 | }
288 |
289 | .steps-control:active {
290 | top: 1px;
291 | background: #a0a0a0;
292 | color: #FFF;
293 | }
294 |
295 | .is-disabled,
296 | .is-disabled:hover {
297 | top: 0;
298 | background: #f2f2f2;
299 | color: #AAA;
300 | cursor: default;
301 | }
302 |
303 | .items--steps {
304 | display: block;
305 | margin-top: 10px;
306 | }
307 |
308 | .step {
309 | display: inline-block;
310 | width: 30px;
311 | height: 30px;
312 | margin-right: 1px;
313 | line-height: 30px;
314 | background: #f2f2f2;
315 | text-align: center;
316 | }
317 |
318 | .step__inp {
319 | position: absolute;
320 | display: none;
321 | }
322 |
323 | .step__lbl {
324 | display: block;
325 | height: 30px;
326 | }
327 |
328 | .is--filled + .step__lbl {
329 | background: lightgray;
330 | }
331 |
332 | :checked + .step__lbl {
333 | position: relative;
334 | z-index: 1;
335 | background: #a0a0a0;
336 | -webkit-box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
337 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
338 | color: #FFF;
339 | }
340 |
341 | .is-hidden {
342 | display: none;
343 | }
344 |
345 | .frames-clear {
346 | position: absolute;
347 | top: 10px;
348 | }
349 | .frames-clear:hover {
350 | padding-top: 1px;
351 | }
352 |
353 | .frames-clear--current {
354 | left: 10px;
355 | border-bottom: 1px dotted;
356 | line-height: 1.2;
357 | color: #555;
358 | cursor: pointer;
359 | }
360 |
361 | .frames-clear--all {
362 | right: 10px;
363 | border-bottom: 1px dotted;
364 | line-height: 1.2;
365 | color: orangered;
366 | cursor: pointer;
367 | }
368 |
369 | .is--sleepy {
370 | color: #777;
371 | }
372 |
373 | /* Codes
374 | ----------------------------- */
375 | .b-codes {
376 | /*display: none;*/
377 | position: absolute;
378 | z-index: 10;
379 | top: 0;
380 | right: 0;
381 | left: 0;
382 | background: rgba(240, 240, 240, 0.9);
383 | -webkit-box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
384 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
385 | }
386 |
387 | .is-open {
388 | right: -.5em;
389 | left: -.5em;
390 | -webkit-box-shadow: 0 0 20px rgba(0, 0, 0, 0.3), 0 0 0 1000px rgba(255, 255, 255, 0.8);
391 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.3), 0 0 0 1000px rgba(255, 255, 255, 0.8);
392 | }
393 |
394 | .b-codes__toggle {
395 | position: absolute;
396 | top: -24px;
397 | right: 10px;
398 | border-bottom: 1px dotted;
399 | line-height: 1.2;
400 | color: #555;
401 | cursor: pointer;
402 | }
403 | .b-codes__toggle:hover {
404 | padding-top: 1px;
405 | }
406 |
407 | .b-codes__wrapper {
408 | display: none;
409 | padding: 20px;
410 | border: 1px solid #BBB;
411 | }
412 | .is-open .b-codes__wrapper {
413 | display: block;
414 | }
415 |
416 | .b-codes--title {
417 | margin-bottom: 6.66667px;
418 | color: #777;
419 | }
420 |
421 | .b-codes__textarea {
422 | display: block;
423 | width: 100%;
424 | height: 120px;
425 | border: 1px solid #CCC;
426 | }
427 |
428 | .textarea--css {
429 | margin-bottom: 20px;
430 | }
431 |
432 | .hello {
433 | display: none;
434 | position: absolute;
435 | z-index: 10;
436 | height: 150px;
437 | width: 100%;
438 | top: -1em;
439 | bottom: -1em;
440 | margin: auto;
441 | background: rgba(0, 0, 0, 0.3);
442 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
443 | text-align: center;
444 | color: #FFF;
445 | }
446 | .hello H2 {
447 | margin-bottom: 10px;
448 | font-size: 4em;
449 | }
450 | .hello SPAN {
451 | font-size: 2em;
452 | }
453 | .hello:before {
454 | content: "";
455 | display: inline-block;
456 | height: 150px;
457 | vertical-align: middle;
458 | }
459 |
460 | .hello__text {
461 | display: inline-block;
462 | vertical-align: middle;
463 | }
464 |
465 | @media (max-width: 760px) {
466 | .hello {
467 | display: block;
468 | }
469 | }
470 |
471 | /*# sourceMappingURL=style.unprefixed.css.map */
472 |
--------------------------------------------------------------------------------
/assets/css/styles.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h2, h3, h4, h5, h6,
2 | p, a, img, b, i, dl, dt, dd, ol, ul, li,
3 | label, article, aside, footer, header, section {
4 | margin: 0;
5 | padding: 0;
6 | border: 0;
7 | font-size: 100%;
8 | font: inherit;
9 | vertical-align: baseline; }
10 |
11 | body {
12 | line-height: 1; }
13 |
14 | ol, ul {
15 | list-style: none; }
16 |
17 | * {
18 | box-sizing: border-box; }
19 |
20 | HTML,
21 | BODY {
22 | height: 100%; }
23 |
24 | BODY {
25 | display: flex;
26 | align-items: center;
27 | justify-content: center;
28 | background: #FFF;
29 | font: 14px/1.4 'Trebuchet MS', Verdana, sans-serif;
30 | color: #333; }
31 |
32 | LABEL {
33 | cursor: pointer; }
34 |
35 | .l-wrapper {
36 | position: relative;
37 | border: 1px solid #CCC;
38 | white-space: nowrap; }
39 | .l-wrapper:after {
40 | content: '';
41 | display: table;
42 | width: 100%;
43 | clear: both; }
44 |
45 | .b-boxes {
46 | position: relative;
47 | text-align: center;
48 | border: 1px solid #CCC;
49 | border-width: 1px 0; }
50 |
51 | .l-zero-gravity {
52 | position: absolute;
53 | width: 100%;
54 | top: 0;
55 | bottom: 0;
56 | right: 0;
57 | left: 0;
58 | margin: auto; }
59 |
60 | .b-box {
61 | position: relative;
62 | display: inline-block;
63 | border: 1px solid #CCC; }
64 | .b-box:nth-of-type(1) {
65 | margin-right: 20px; }
66 |
67 | .b-panel {
68 | padding: 10px;
69 | color: #888; }
70 | .b-panel:before, .b-panel:after {
71 | content: '';
72 | display: table;
73 | width: 100%;
74 | clear: both; }
75 |
76 | .b-title {
77 | display: inline-block;
78 | padding-right: 10px;
79 | line-height: 30px; }
80 |
81 | .b-steps .b-title {
82 | float: none;
83 | display: inline-block;
84 | margin: 0 auto;
85 | padding: 0; }
86 |
87 | /* Paint Box
88 | ----------------------------- */
89 | .b-box--paint {
90 | overflow: hidden;
91 | border-width: 0 1px 1px 0;
92 | background-image: linear-gradient(to right, #CCC 1px, transparent 1px), linear-gradient(to bottom, #CCC 1px, transparent 1px);
93 | background-position: 0 0; }
94 |
95 | /* Labels
96 | ----------------------------- */
97 | .cell {
98 | display: block;
99 | float: left; }
100 |
101 | .cell__inp {
102 | position: absolute;
103 | display: none; }
104 |
105 | .cell__lbl {
106 | display: block;
107 | border-radius: 0;
108 | /*box-shadow: 0 0 2px #999 inset;*/ }
109 |
110 | :checked + .cell__lbl {
111 | position: relative; }
112 |
113 | .is-colored {
114 | background: orange; }
115 |
116 | /* Result Box
117 | ----------------------------- */
118 | .b-box--result {
119 | overflow: hidden; }
120 |
121 | /* Dotts
122 | ----------------------------- */
123 | .dot {
124 | display: block;
125 | position: absolute;
126 | border-radius: 0; }
127 |
128 | .dot--previous {
129 | opacity: .2; }
130 |
131 | @keyframes shadows {}/* Palette
132 | ----------------------------- */
133 | .b-palette {
134 | display: inline-block; }
135 |
136 | .items--colors {
137 | display: inline-block;
138 | vertical-align: middle; }
139 |
140 | .color {
141 | display: inline-block;
142 | width: 30px;
143 | height: 30px; }
144 |
145 | .color__inp {
146 | display: none; }
147 |
148 | .color__lbl {
149 | display: block;
150 | height: 30px; }
151 |
152 | :checked + .color__lbl {
153 | position: relative;
154 | z-index: 1;
155 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3); }
156 |
157 | /* Color Controls
158 | ----------------------------- */
159 | .items--colors-controls {
160 | display: inline-block;
161 | position: relative;
162 | height: 30px;
163 | margin-left: 5px;
164 | vertical-align: middle; }
165 |
166 | .colors-controls__item {
167 | position: absolute;
168 | border: 10px solid transparent;
169 | border-color: #a0a0a0 transparent;
170 | border-width: 10px 4px;
171 | cursor: pointer; }
172 | .colors-controls__item:hover {
173 | border-color: #878787 transparent; }
174 | .colors-controls__item:active {
175 | border-color: #545454 transparent; }
176 |
177 | .colors-controls__item--up {
178 | top: 0;
179 | border-top: 0; }
180 | .colors-controls__item--up:active {
181 | top: 2px; }
182 |
183 | .colors-controls__item--down {
184 | bottom: 0;
185 | border-bottom: 0; }
186 | .colors-controls__item--down:active {
187 | bottom: -2px; }
188 |
189 | /* Panel
190 | ----------------------------- */
191 | .b-panel {
192 | position: relative; }
193 |
194 | .b-panel__item {
195 | float: left;
196 | margin-left: 32px; }
197 | .b-panel__item:first-child {
198 | margin-left: 0; }
199 |
200 | .text--value {
201 | width: 3.5em;
202 | height: 30px;
203 | line-height: 30px;
204 | pading: 0;
205 | border: 1px solid #CCC;
206 | border-radius: 5px;
207 | text-align: center; }
208 |
209 | /* Steps
210 | ----------------------------- */
211 | .b-steps {
212 | text-align: center;
213 | -webkit-user-select: none;
214 | -ms-user-select: none;
215 | user-select: none; }
216 |
217 | .steps-control {
218 | display: inline-block;
219 | position: relative;
220 | width: 24px;
221 | height: 24px;
222 | line-height: 24px;
223 | margin: 0 6px;
224 | top: 0;
225 | background: lightgray;
226 | font-weight: bold;
227 | color: #444;
228 | cursor: pointer;
229 | transition: all .2s; }
230 |
231 | .steps-control:hover {
232 | top: -1px;
233 | background: #f2f2f2;
234 | color: #555; }
235 |
236 | .steps-control:active {
237 | top: 1px;
238 | background: #a0a0a0;
239 | color: #FFF; }
240 |
241 | .is-disabled,
242 | .is-disabled:hover {
243 | top: 0;
244 | background: #f2f2f2;
245 | color: #AAA;
246 | cursor: default; }
247 |
248 | .items--steps {
249 | display: block;
250 | margin-top: 10px; }
251 |
252 | .step {
253 | display: inline-block;
254 | width: 30px;
255 | height: 30px;
256 | margin-right: 1px;
257 | line-height: 30px;
258 | background: #f2f2f2;
259 | text-align: center; }
260 |
261 | .step__inp {
262 | position: absolute;
263 | display: none; }
264 |
265 | .step__lbl {
266 | display: block;
267 | height: 30px; }
268 |
269 | .is--filled + .step__lbl {
270 | background: lightgray; }
271 |
272 | :checked + .step__lbl {
273 | position: relative;
274 | z-index: 1;
275 | background: #a0a0a0;
276 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
277 | color: #FFF; }
278 |
279 | .is-hidden {
280 | display: none; }
281 |
282 | .frames-clear {
283 | position: absolute;
284 | top: 10px; }
285 | .frames-clear:hover {
286 | padding-top: 1px; }
287 |
288 | .frames-clear--current {
289 | left: 10px;
290 | border-bottom: 1px dotted;
291 | line-height: 1.2;
292 | color: #555;
293 | cursor: pointer; }
294 |
295 | .frames-clear--all {
296 | right: 10px;
297 | border-bottom: 1px dotted;
298 | line-height: 1.2;
299 | color: orangered;
300 | cursor: pointer; }
301 |
302 | .is--sleepy {
303 | color: #777; }
304 |
305 | /* Codes
306 | ----------------------------- */
307 | .b-codes {
308 | /*display: none;*/
309 | position: absolute;
310 | z-index: 10;
311 | top: 0;
312 | right: 0;
313 | left: 0;
314 | background: rgba(240, 240, 240, 0.9);
315 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); }
316 |
317 | .is-open {
318 | right: -.5em;
319 | left: -.5em;
320 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.3), 0 0 0 1000px rgba(255, 255, 255, 0.8); }
321 |
322 | .b-codes__toggle {
323 | position: absolute;
324 | top: -24px;
325 | right: 10px;
326 | border-bottom: 1px dotted;
327 | line-height: 1.2;
328 | color: #555;
329 | cursor: pointer; }
330 | .b-codes__toggle:hover {
331 | padding-top: 1px; }
332 |
333 | .b-codes__wrapper {
334 | display: none;
335 | padding: 20px;
336 | border: 1px solid #BBB; }
337 | .is-open .b-codes__wrapper {
338 | display: block; }
339 |
340 | .b-codes--title {
341 | margin-bottom: 6.66667px;
342 | color: #777; }
343 |
344 | .b-codes__textarea {
345 | display: block;
346 | width: 100%;
347 | height: 120px;
348 | border: 1px solid #CCC; }
349 |
350 | .textarea--css {
351 | margin-bottom: 20px; }
352 |
353 | .hello {
354 | display: none;
355 | position: absolute;
356 | z-index: 10;
357 | height: 150px;
358 | width: 100%;
359 | top: -1em;
360 | bottom: -1em;
361 | margin: auto;
362 | background: rgba(0, 0, 0, 0.3);
363 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
364 | text-align: center;
365 | color: #FFF; }
366 | .hello H2 {
367 | margin-bottom: 10px;
368 | font-size: 4em; }
369 | .hello SPAN {
370 | font-size: 2em; }
371 | .hello:before {
372 | content: "";
373 | display: inline-block;
374 | height: 150px;
375 | vertical-align: middle; }
376 |
377 | .hello__text {
378 | display: inline-block;
379 | vertical-align: middle; }
380 |
381 | @media (max-width: 760px) {
382 |
383 | .hello {
384 | display: block; } }
385 |
--------------------------------------------------------------------------------
/assets/css/styles.min.css:
--------------------------------------------------------------------------------
1 | a,article,aside,b,body,dd,div,dl,dt,footer,h1,h2,h3,h4,h5,h6,header,html,i,img,label,li,ol,p,section,span,ul{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}body{line-height:1}ol,ul{list-style:none}*{box-sizing:border-box}BODY,HTML{height:100%}BODY{display:flex;align-items:center;justify-content:center;background:#fff;font:14px/1.4 Trebuchet MS,Verdana,sans-serif;color:#333}LABEL{cursor:pointer}.l-wrapper{position:relative;border:1px solid #ccc;white-space:nowrap}.l-wrapper:after{content:"";display:table;width:100%;clear:both}.b-boxes{position:relative;text-align:center;border:1px solid #ccc;border-width:1px 0}.l-zero-gravity{position:absolute;width:100%;top:0;bottom:0;right:0;left:0;margin:auto}.b-box{position:relative;display:inline-block;border:1px solid #ccc}.b-box:first-of-type{margin-right:20px}.b-panel{padding:10px;color:#888}.b-panel:after,.b-panel:before{content:"";display:table;width:100%;clear:both}.b-title{display:inline-block;padding-right:10px;line-height:30px}.b-steps .b-title{float:none;display:inline-block;margin:0 auto;padding:0}.b-box--paint{overflow:hidden;border-width:0 1px 1px 0;background-image:linear-gradient(90deg,#ccc 1px,transparent 0),linear-gradient(180deg,#ccc 1px,transparent 0);background-position:0 0}.cell{display:block;float:left}.cell__inp{position:absolute;display:none}.cell__lbl{display:block;border-radius:0}:checked+.cell__lbl{position:relative}.is-colored{background:orange}.b-box--result{overflow:hidden}.dot{display:block;position:absolute;border-radius:0}.dot--previous{opacity:.2}.b-palette,.items--colors{display:inline-block}.items--colors{vertical-align:middle}.color{display:inline-block;width:30px;height:30px}.color__inp{display:none}.color__lbl{display:block;height:30px}:checked+.color__lbl{position:relative;z-index:1;box-shadow:0 0 0 3px rgba(0,0,0,.3)}.items--colors-controls{display:inline-block;position:relative;height:30px;margin-left:5px;vertical-align:middle}.colors-controls__item{position:absolute;border:10px solid transparent;border-color:#a0a0a0 transparent;border-width:10px 4px;cursor:pointer}.colors-controls__item:hover{border-color:#878787 transparent}.colors-controls__item:active{border-color:#545454 transparent}.colors-controls__item--up{top:0;border-top:0}.colors-controls__item--up:active{top:2px}.colors-controls__item--down{bottom:0;border-bottom:0}.colors-controls__item--down:active{bottom:-2px}.b-panel{position:relative}.b-panel__item{float:left;margin-left:32px}.b-panel__item:first-child{margin-left:0}.text--value{width:3.5em;height:30px;line-height:30px;pading:0;border:1px solid #ccc;border-radius:5px;text-align:center}.b-steps{text-align:center;-webkit-user-select:none;-ms-user-select:none;user-select:none}.steps-control{display:inline-block;position:relative;width:24px;height:24px;line-height:24px;margin:0 6px;top:0;background:#d3d3d3;font-weight:700;color:#444;cursor:pointer;transition:all .2s}.steps-control:hover{top:-1px;background:#f2f2f2;color:#555}.steps-control:active{top:1px;background:#a0a0a0;color:#fff}.is-disabled,.is-disabled:hover{top:0;background:#f2f2f2;color:#aaa;cursor:default}.items--steps{display:block;margin-top:10px}.step{display:inline-block;width:30px;height:30px;margin-right:1px;line-height:30px;background:#f2f2f2;text-align:center}.step__inp{position:absolute;display:none}.step__lbl{display:block;height:30px}.is--filled+.step__lbl{background:#d3d3d3}:checked+.step__lbl{position:relative;z-index:1;background:#a0a0a0;box-shadow:0 0 0 3px rgba(0,0,0,.3);color:#fff}.is-hidden{display:none}.frames-clear{position:absolute;top:10px}.frames-clear:hover{padding-top:1px}.frames-clear--current{left:10px;color:#555}.frames-clear--all,.frames-clear--current{border-bottom:1px dotted;line-height:1.2;cursor:pointer}.frames-clear--all{right:10px;color:#ff4500}.is--sleepy{color:#777}.b-codes{position:absolute;z-index:2;top:0;right:0;left:0;background:hsla(0,0%,94%,.9);box-shadow:0 0 20px rgba(0,0,0,.3)}.is-open{right:-.5em;left:-.5em;box-shadow:0 0 20px rgba(0,0,0,.3),0 0 0 1000px hsla(0,0%,100%,.8)}.b-codes__toggle{position:absolute;top:-24px;right:10px;border-bottom:1px dotted;line-height:1.2;color:#555;cursor:pointer}.b-codes__toggle:hover{padding-top:1px}.b-codes__wrapper{display:none;padding:20px;border:1px solid #bbb}.is-open .b-codes__wrapper{display:block}.b-codes--title{margin-bottom:6.66667px;color:#777}.b-codes__textarea{display:block;width:100%;height:120px;border:1px solid #ccc}.textarea--css{margin-bottom:20px}.hello{display:none;position:absolute;z-index:2;height:150px;width:100%;top:-1em;bottom:-1em;margin:auto;background:rgba(0,0,0,.3);text-shadow:0 0 3px rgba(0,0,0,.5);text-align:center;color:#fff}.hello H2{margin-bottom:10px;font-size:4em}.hello SPAN{font-size:2em}.hello:before{content:"";height:150px}.hello:before,.hello__text{display:inline-block;vertical-align:middle}@media (max-width:760px){.hello{display:block}}
--------------------------------------------------------------------------------
/assets/js/script.js:
--------------------------------------------------------------------------------
1 | var line = '------------------------';
2 |
3 | function ShadowPainter() {
4 | this.timer;
5 | this.isMousePressed = false;
6 |
7 | this.classNames = {
8 | wrapper: '.l-wrapper',
9 | paintBox: '.b-box--paint',
10 | resultBox: '.b-box--result',
11 | resultDot: '.b-box--result .dot',
12 | palette: '.b-palette',
13 | steps: '.b-steps',
14 |
15 | codes: '.b-codes',
16 | codesToggle: '.b-codes__toggle',
17 | codesCSS: '.textarea--css',
18 | codesHtml: '.textarea--html',
19 |
20 | durationInp: '.text--duration',
21 | sizeInp: '.text--size',
22 | dotsInp: '.text--dots',
23 | isRunning: 'is-running',
24 | };
25 |
26 | this.Elems = {};
27 |
28 | this.Cell = {
29 | className: 'cell',
30 | inputType: 'checkbox',
31 | inputClass: 'cell__inp',
32 | labelClass: 'cell__lbl',
33 | inputData: 'data-hpos="{hpos}" data-vpos="{vpos}" ',
34 | labelContent: '',
35 | dots: ''
36 | };
37 |
38 | this.Palettes = [
39 | ['#3FB8AF','#7FC7AF','#DAD8A7','#FF9E9D','#FF3D7F'],
40 | ['#468966','#FFF0A5','#FFB03B','#B64926','#8E2800'],
41 | ['#004358','#1F8A70','#BEDB39','#FFE11A','#FD7400'],
42 | ['#96CA2D','#B5E655','#EDF7F2','#4BB5C1','#7FC6BC'],
43 | ['#2E0927','#D90000','#FF2D00','#FF8C00','#04756F'],
44 | ['#FCFFF5','#D1DBBD','#91AA9D','#3E606F','#193441'],
45 | ['#332532','#644D52','#F77A52','#FF974F','#A49A87']
46 | ];
47 |
48 | this.Colors = this.initColors();
49 | this.Step = this.initStep();
50 |
51 | this.stylesClassNames = {
52 | config: 'configBox',
53 | shadows: 'stylesBox',
54 | colors: 'colorsBox'
55 | };
56 | this.Styles = {};
57 |
58 | this.Output = {
59 | HTML: '',
60 | CSS: '',
61 | Animation: '',
62 | comment: 'Created in shadowPainter : )'
63 | };
64 |
65 | this.Scene = {
66 | oneSide: 5,// dottes in line
67 | oneSideMax: 30,// dottes in line
68 | size: 250,
69 | dotSize: 30,// pixels
70 | padding: 20,// pixels. Don't change it
71 | border: 1// pixels
72 | };
73 |
74 | this.Anim = {
75 | steps: 5,
76 | stepsMax: 20,
77 | duration: '1s',
78 | name: 'shadows',
79 | keyframes: findKeyFrames('shadows')
80 | };
81 | this.Anim.rules = this.Anim.keyframes.cssRules;
82 |
83 | this.isCodeOpened = false;
84 |
85 | this.Frames = {};
86 | this.currentFrame = 0;
87 |
88 | this.init = function () {
89 | this.createTemplates();
90 | this.createStylesBoxes();
91 |
92 | this.initElements();
93 | this.addConfig();
94 | this.createInputsSet();
95 | this.createFramesSet();
96 | this.createPalette();
97 | this.createSteps();
98 | this.createCodes();
99 | this.createDurationInp();
100 | this.createSizeInp();
101 | this.createDotsInp();
102 | };
103 |
104 | } // End ShadowPainter()
105 |
106 | // -----------------------------------------
107 |
108 | ShadowPainter.prototype.setTimer = function(func, params) {
109 | if (this.timer) {
110 | this.clearTimeout(this.timer);
111 | }
112 | var execFunc = function () {
113 | func(params);
114 | };
115 | this.timer = this.setTimeout(execFunc , 50);
116 | };
117 |
118 | // -----------------------------------------
119 |
120 | ShadowPainter.prototype.getAnimStr = function() {
121 | return `${this.Anim.duration} ${this.Anim.name} linear infinite`;
122 | };
123 |
124 | // -----------------------------------------
125 |
126 | ShadowPainter.prototype.initElements = function () {
127 | for (var className in this.classNames) {
128 | this.Elems[className] = document.querySelector(this.classNames[className]);
129 | }
130 | };
131 |
132 | // -----------------------------------------
133 |
134 | ShadowPainter.prototype.setParams = function () {
135 | let dotSize = (this.Scene.size / this.Scene.oneSide);
136 | this.Scene.dotSize = dotSize.toFixed();
137 | this.Scene.size = this.Scene.dotSize * this.Scene.oneSide;
138 |
139 | this.configElemParams = {
140 | '.l-wrapper': {
141 | 'width': 700, // size * 2 + this.Scene.padding * 3 + border*6
142 | 'height': 490, // size + this.Scene.padding * 2 + border*4
143 | },
144 | '.b-boxes': {
145 | 'height': 340
146 | },
147 | '.l-zero-gravity': {
148 | 'height': this.Scene.size + this.Scene.border
149 | },
150 | '.b-box': {
151 | 'width': this.Scene.size + this.Scene.border,
152 | 'height': this.Scene.size
153 | },
154 | '.cell__lbl': {
155 | 'width': this.Scene.dotSize,
156 | 'height': this.Scene.dotSize
157 | },
158 | '.dot': {
159 | 'width': this.Scene.dotSize,
160 | 'height': this.Scene.dotSize,
161 | 'top': '-' + this.Scene.dotSize,
162 | 'left': '-' + this.Scene.dotSize
163 | },
164 | '.is-running': {
165 | 'animation': this.getAnimStr()
166 | },
167 | '.b-box--paint': {
168 | 'background-size': this.Scene.dotSize + ' ' + this.Scene.dotSize
169 | }
170 | };
171 | };
172 |
173 | // -----------------------------------------
174 |
175 | ShadowPainter.prototype.setOutputParams = function () {
176 | this.outputElemParams = {
177 | '.box': {
178 | 'position': 'absolute',
179 | 'top': '0',
180 | 'bottom': '0',
181 | 'left': '0',
182 | 'right': '0',
183 | 'margin': 'auto',
184 | 'width': this.Scene.size,
185 | 'height': this.Scene.size,
186 | 'overflow': 'hidden',
187 | 'border': '1px solid #DDD'
188 | },
189 | '.dot': {
190 | 'display': 'block',
191 | 'position': 'absolute',
192 | 'width': this.Scene.dotSize,
193 | 'height': this.Scene.dotSize,
194 | 'top': '-' + this.Scene.dotSize,
195 | 'left': '-' + this.Scene.dotSize,
196 | 'animation': this.getAnimStr()
197 | }
198 | };
199 | };
200 |
201 | // -----------------------------------------
202 |
203 | ShadowPainter.prototype.addConfig = function () {
204 | this.setParams();
205 |
206 | var styles = '';
207 | for (var elem in this.configElemParams) {
208 | var className = elem;
209 | var elemStyles = '';
210 | var params = this.configElemParams[elem];
211 | for (var item in params) {
212 | var value = addUnits(params[item], item);
213 | elemStyles += item + ': ' + value + ';\n';
214 | }
215 | styles += className + ' {\n' + elemStyles + '}\n';
216 | }
217 |
218 | this.Styles.config.innerHTML = styles;
219 | };
220 |
221 | // -----------------------------------------
222 |
223 | ShadowPainter.prototype.createStylesBoxes = function () {
224 | for (var styleBox in this.stylesClassNames) {
225 | this.Styles[styleBox] = addStylesElem(this.stylesClassNames[styleBox]);
226 | }
227 | };
228 |
229 | // -----------------------------------------
230 |
231 | ShadowPainter.prototype.createTemplates = function () {
232 | var templatesConfig = [this.Cell, this.Colors, this.Step];
233 |
234 | for (var i = 0; i < templatesConfig.length; i++) {
235 | var item = templatesConfig[i];
236 | item.template = createTemplate(item);
237 | }
238 | };
239 |
240 | // -----------------------------------------
241 |
242 | ShadowPainter.prototype.createControls = function (data) {
243 | var output = '';
244 |
245 | var counter = 0;
246 | for (var item in data.list) {
247 | data.replacements['{action}'] = item;
248 | data.replacements['{text}'] = data.list[ item ];
249 | output += fillTemplate(data.template, data.replacements);
250 |
251 | if (counter === 0 && data.insertBetween) {
252 | output += data.insertBetween;
253 | }
254 | counter++;
255 | }
256 | return output;
257 | };
258 |
259 | // -----------------------------------------
260 |
261 | ShadowPainter.prototype.addDataDefautlt = function (elem, defaultValue) {
262 | var defData = elem.getAttribute('data-default');
263 |
264 | if (defData === null) {
265 | elem.setAttribute('data-default', defaultValue);
266 | }
267 | };
268 |
269 | // -----------------------------------------
270 |
271 | ShadowPainter.prototype.addEvents = function (itemsClass, func) {
272 | itemsClass = checkClassDot(itemsClass);
273 | var items = document.querySelectorAll(itemsClass);
274 | var parent = this;
275 |
276 | for (var i = 0; i < items.length; i++) {
277 | items[i].onclick = function () {
278 | func.call(parent, this);
279 | };
280 | }
281 | };
282 |
283 | // -----------------------------------------
284 |
285 | ShadowPainter.prototype.addOverEvents = function (itemsClass, func) {
286 | itemsClass = checkClassDot(itemsClass);
287 | var items = document.querySelectorAll(itemsClass);
288 | var parent = this;
289 |
290 | for (var i = 0; i < items.length; i++) {
291 | items[i].onmousedown = function () {
292 | this.isMousePressed = true;
293 | };
294 |
295 | items[i].onmouseup = function () {
296 | this.isMousePressed = false;
297 | };
298 |
299 | items[i].onmouseover = function () {
300 | if (this.isMousePressed) {
301 | func.call(parent, this);
302 | }
303 | };
304 | }
305 | };
306 |
307 | // -----------------------------------------
308 |
309 | ShadowPainter.prototype.checkInputValue = function (params) {
310 | var elem = params.elem;
311 | var func = params.func;
312 | var parent = params.parent;
313 |
314 | var minMax = minMaxDef(elem);
315 | var isNan = valueSetDefaultIfNAN(elem);
316 |
317 | if (isNan) {
318 | elem.value = isNan;
319 | }
320 |
321 | if (minMax) {
322 | elem.value = minMax;
323 | }
324 |
325 | func.call(parent, elem);
326 | };
327 |
328 | // -----------------------------------------
329 |
330 | ShadowPainter.prototype.addOnChangeEvents = function (itemsClass, func) {
331 | var items = document.querySelectorAll(itemsClass);
332 | var parent = this;
333 |
334 | var params = {
335 | func: func,
336 | parent: parent
337 | };
338 |
339 | for (var i = 0; i < items.length; i++) {
340 | items[i].onkeyup = function (event) {
341 | params.elem = this;
342 |
343 | if (event.keyCode === 38 || event.keyCode === 40) {
344 |
345 | this.value = getValByKeyCode(this, event.keyCode, event.shiftKey);
346 | func.call(parent, this);
347 | }
348 | else {
349 | this.setTimer(parent.checkInputValue, params);
350 | }
351 | };
352 |
353 | items[i].onchange = function () {
354 | params.elem = this;
355 | parent.checkInputValue(params);
356 | };
357 |
358 | items[i].onblur = function () {
359 | params.elem = this;
360 | parent.checkInputValue(params);
361 | };
362 | }
363 | };
364 |
365 | // -----------------------------------------
366 |
367 | ShadowPainter.prototype.createInputsSet = function () {
368 | this.Elems.paintBox.innerHTML = this.Cell.dots;
369 | var output = '';
370 |
371 | for (var i = 0; i < this.Scene.oneSide * this.Scene.oneSide; i++) {
372 | var hpos = i % this.Scene.oneSide + 1;
373 | var vpos = Math.floor(i / this.Scene.oneSide) + 1;
374 |
375 | var replacements = {
376 | '{i}': i,
377 | '{hpos}': hpos,
378 | '{vpos}': vpos
379 | };
380 | var checkBox = fillTemplate(this.Cell.template, replacements);
381 | output += checkBox;
382 | }
383 |
384 | this.Elems.paintBox.innerHTML += `
`;
385 |
386 | this.addOverEvents(this.Cell.labelClass, this.onOverLabel);
387 | this.addEvents(this.Cell.inputClass, this.onClickCell);
388 | };
389 |
390 | // -----------------------------------------
391 |
392 | ShadowPainter.prototype.createFramesSet = function () {
393 | for (var k = 0; k < this.Anim.stepsMax; k++) {
394 | this.Frames[k] = {active: 0};
395 |
396 | for (var hpos = 0; hpos < this.Scene.oneSideMax; hpos++) { // verticals
397 | this.Frames[k][hpos] = {};
398 |
399 | for (var vpos = 0; vpos < this.Scene.oneSideMax; vpos++) { // gorizontals
400 |
401 | this.Frames[k][hpos][vpos] = {
402 | 'hpos': hpos,
403 | 'vpos': vpos,
404 | 'color': this.Colors.transparent
405 | };
406 | } // End gorizontals
407 | } // End verticals
408 | }
409 | };
410 |
411 | // -----------------------------------------
412 |
413 | ShadowPainter.prototype.resetCurrentFrame = function () {
414 | var k = this.currentFrame;
415 | this.Frames[k] = {active: 0};
416 |
417 | for (var hpos = 0; hpos < this.Scene.oneSideMax; hpos++) { // verticals
418 | this.Frames[k][hpos] = {};
419 |
420 | for (var vpos = 0; vpos < this.Scene.oneSideMax; vpos++) { // gorizontals
421 | this.Frames[k][hpos][vpos] = {
422 | 'color': this.Colors.transparent
423 | };
424 | } // End gorizontals
425 | } // End verticals
426 | };
427 |
428 | // -----------------------------------------
429 |
430 | ShadowPainter.prototype.toggleColorClass = function (elem) {
431 | var findClass = this.Colors.className + '--';
432 | var classes = elem.classList;
433 |
434 | for (var i = 0; i < classes.length; i++) {
435 |
436 | if (classes[i].indexOf(findClass) >= 0) {
437 | classes.remove(classes[i]);
438 | return;
439 | }
440 | }
441 |
442 | classes.add(findClass + this.Colors.currentNum);
443 | };
444 |
445 | // -----------------------------------------
446 |
447 | ShadowPainter.prototype.onClickCell = function (elem) {
448 | this.updateFrames(elem);
449 | };
450 |
451 | // -----------------------------------------
452 |
453 | ShadowPainter.prototype.onOverLabel = function (elem) {
454 | var input = elem.previousSibling;
455 |
456 | if (input.checked === true) {
457 | input.checked = false;
458 | }
459 | else {
460 | input.checked = true;
461 | }
462 |
463 | this.updateFrames(input);
464 | };
465 |
466 | // -----------------------------------------
467 |
468 | ShadowPainter.prototype.updateFrames = function (elem) {
469 | var hpos = elem.getAttribute('data-hpos');
470 | var vpos = elem.getAttribute('data-vpos');
471 |
472 | var place = this.Frames[this.currentFrame];
473 | var color = this.Colors.transparent;
474 |
475 | if (elem.checked) {
476 | color = this.Colors.current;
477 | place.active++;
478 | }
479 | else {
480 | place.active--;
481 | }
482 |
483 | place[hpos][vpos].color = color;
484 | this.paintShadow();
485 | };
486 |
487 | // -----------------------------------------
488 |
489 | ShadowPainter.prototype.paintShadow = function () {
490 | var styles = '';
491 | var framesLength = this.Anim.steps; // objLength(this.Frames);
492 | var perc = this.Anim.steps === 1 ? 0 : (100 / framesLength).toFixed(3);
493 | var dottes = this.Frames[this.currentFrame];
494 | var shadows = this.createShadow(dottes);
495 |
496 | styles = '.b-box--paint .dot {\n ' + shadows + ' \n}\n';
497 |
498 | dottes = this.Frames[0];
499 | shadows = this.createShadow(dottes);
500 | styles += this.classNames.resultDot + ' {\n ' + shadows + ' \nanimation-duration: ' + this.Anim.duration + ';\n}\n';
501 |
502 | if (this.currentFrame > 0) {
503 | dottes = this.Frames[this.currentFrame - 1];
504 | shadows = this.createShadow(dottes);
505 |
506 | styles += '.b-box--paint .dot--previous {\n ' + shadows + ' \n}\n';
507 | }
508 |
509 | this.Styles.shadows.innerHTML = styles;
510 |
511 | this.replaceAnimation({perc: perc});
512 | };
513 |
514 | // -----------------------------------------
515 |
516 | ShadowPainter.prototype.createShadow = function (dottes, is_value) {
517 | if (dottes === undefined) {
518 | return;
519 | }
520 |
521 | var shadows = '';
522 | var if_first = true;
523 |
524 | for (var hpos = 0; hpos < this.Scene.oneSide + 1; hpos++) {
525 | for (var vpos = 0; vpos < this.Scene.oneSide + 1; vpos++) {
526 | var dot = dottes[hpos][vpos];
527 |
528 | var hpos_px = dot.hpos * this.Scene.dotSize + 'px';
529 | var vpos_px = dot.vpos * this.Scene.dotSize + 'px';
530 | var color = this.Colors.transparent;
531 |
532 |
533 | if (dot.color !== this.Colors.transparent) {
534 | color = dot.color;
535 | }
536 |
537 | if (if_first) {
538 | if_first = false;
539 | }
540 | else {
541 | shadows += ', ';
542 | }
543 |
544 | shadows += hpos_px + ' ' + vpos_px + ' 0 0 ' + color;
545 | }
546 | }
547 |
548 | if (!is_value) {
549 | shadows = 'box-shadow: ' + shadows + ';';
550 | }
551 |
552 | return shadows;
553 | };
554 |
555 | // -----------------------------------------
556 |
557 | ShadowPainter.prototype.deleteKeyframes = function () {
558 | var rules = this.Anim.rules;
559 | var keyFrames = this.Anim.keyframes;
560 | const max = 1000;
561 | let counter = 0;
562 |
563 | while (keyFrames.cssRules.length > 0 && counter < max) {
564 | const {keyText} = keyFrames.cssRules[0];
565 | keyFrames.deleteRule(keyText);
566 |
567 | counter++;
568 | }
569 | };
570 |
571 | // -----------------------------------------
572 |
573 | ShadowPainter.prototype.replaceAnimation = function (animation) {
574 | this.Output.Animation = '';
575 | this.deleteKeyframes();
576 |
577 | if (this.Anim.steps === 1) {
578 | this.restartAnimation();
579 | return;
580 | }
581 |
582 | for (var step = 0; step < this.Anim.steps; step++) {
583 | var anim_dottes = this.Frames[step];
584 | var anim_shadows = this.createShadow(anim_dottes);
585 | var stepPercents = +(animation.perc * step).toFixed(3);
586 | var frameRule = `${stepPercents}% {\n${anim_shadows}\n}`;
587 |
588 | this.Anim.keyframes.appendRule(frameRule);
589 | this.Output.Animation += frameRule + '\n';
590 | }
591 |
592 | this.restartAnimation();
593 | };
594 |
595 | // -----------------------------------------
596 |
597 | ShadowPainter.prototype.restartAnimation = function () {
598 | var resultDot = document.querySelector(this.classNames.resultDot);
599 | resultDot.classList.remove(this.classNames.isRunning);
600 | resultDot.classList.add(this.classNames.isRunning);
601 | };
602 |
603 | // -----------------------------------------
604 |
605 | ShadowPainter.prototype.createPalette = function () {
606 | const paletteControls = this.createControls(this.Colors.upDown);
607 | this.Elems.palette.innerHTML += 'Colors
';
608 | this.Elems.palette.innerHTML += '';
609 | this.Elems.palette.innerHTML += ``;
610 |
611 | this.fillPalette();
612 | this.addEvents(this.Colors.inputClass, this.onClickColor);
613 |
614 | var first = document.querySelector(checkClassDot(this.Colors.inputClass));
615 | first.checked = true;
616 |
617 | this.addEvents(this.Colors.controlClass, this.onClickColorControl);
618 | };
619 |
620 | // -----------------------------------------
621 |
622 | ShadowPainter.prototype.fillPalette = function () {
623 | var output = '';
624 | var colorsItems = document.querySelector('.items--colors');
625 | this.Styles.colors.innerHTML = '';
626 |
627 | for (var i = 0; i < this.Colors.list.length; i++) {
628 | var replacements = {
629 | '{i}': i,
630 | '{color}': this.Colors.list[i]
631 | };
632 | var colorItem = fillTemplate(this.Colors.template, replacements);
633 | var colorStyle = fillTemplate(this.Colors.StyleTempl, replacements);
634 | this.Styles.colors.innerHTML += colorStyle;
635 | output += colorItem;
636 | }
637 |
638 | colorsItems.innerHTML = output;
639 | };
640 |
641 | // -----------------------------------------
642 |
643 | ShadowPainter.prototype.reFillPalette = function () {
644 | var colorsItems = document.querySelectorAll(checkClassDot(this.Colors.inputClass));
645 | this.Styles.colors.innerHTML = '';
646 |
647 | for (var i = 0; i < this.Colors.list.length; i++) {
648 | colorsItems[i].setAttribute('data-color', this.Colors.list[i]);
649 | var replacements = {
650 | '{i}': i,
651 | '{color}': this.Colors.list[i]
652 | };
653 | var colorStyle = fillTemplate(this.Colors.StyleTempl, replacements);
654 |
655 | this.Styles.colors.innerHTML += colorStyle;
656 | }
657 | };
658 |
659 | // -----------------------------------------
660 |
661 | ShadowPainter.prototype.onClickColor = function (elem) {
662 | this.Colors.current = elem.getAttribute('data-color');
663 | this.Colors.currentNum = elem.getAttribute('data-color-num');
664 | this.Colors.classCurrent = this.Colors.className + '--' + this.Colors.currentNum;
665 | };
666 |
667 | // -----------------------------------------
668 |
669 | ShadowPainter.prototype.onClickColorControl = function (elem) {
670 | var direct = elem.getAttribute('data-direction');
671 | var max = this.Palettes.length - 1;
672 |
673 | if (direct === 'up') {
674 | if (this.Colors.currentListNum < max) {
675 | this.Colors.currentListNum++;
676 | }
677 | else {
678 | this.Colors.currentListNum = 0;
679 | }
680 | }
681 | else {
682 | if (this.Colors.currentListNum > 0) {
683 | this.Colors.currentListNum--;
684 | }
685 | else {
686 | this.Colors.currentListNum = max;
687 | }
688 | }
689 |
690 | this.Colors.list = this.Palettes[this.Colors.currentListNum];
691 | this.Colors.current = this.Colors.list[this.Colors.currentNum];
692 | this.Colors.classCurrent = this.Colors.className + '--' + this.Colors.currentNum;
693 |
694 | this.reFillPalette();
695 | };
696 |
697 | // -----------------------------------------
698 |
699 | ShadowPainter.prototype.createSteps = function () {
700 | var output = '';
701 | const plusMinusControls = this.createControls(this.Step.plusMinus);
702 | this.Elems.steps.innerHTML += `${plusMinusControls}
`;
703 |
704 | for (var i = 0; i < this.Anim.stepsMax; i++) {
705 | var customClass = i < this.Anim.steps ? '' : ' ' + this.Step.hiddenClass;
706 |
707 | var replacements = {
708 | '{i}': i,
709 | '{i+1}': i+1,
710 | '{customClass}': customClass
711 | };
712 |
713 | var stepItem = fillTemplate(this.Step.template, replacements);
714 | output += stepItem;
715 | }
716 |
717 | this.Elems.steps.innerHTML += ``;
718 |
719 | this.Elems.steps.innerHTML += this.createControls(this.Step.clearFrames);
720 |
721 | var first = document.querySelector(checkClassDot(this.Step.inputClass));
722 | first.checked = true;
723 |
724 | this.addEvents(this.Step.inputClass, this.onClickStep);
725 | this.addEvents(this.Step.controlClass, this.onClickStepControl);
726 | this.addEvents(this.Step.clearFramesClass, this.onClickClearFrames);
727 | };
728 |
729 | // -----------------------------------------
730 |
731 | ShadowPainter.prototype.onClickStep = function (elem) {
732 | this.currentFrame = elem.getAttribute('data-step-num');
733 | this.paintShadow();
734 | this.updateCells();
735 | };
736 |
737 | // -----------------------------------------
738 |
739 | ShadowPainter.prototype.onClickStepControl = function (elem) {
740 | var action = elem.getAttribute('data-action');
741 | var stepsItems = document.querySelectorAll(checkClassDot(this.Step.className));
742 | var division = stepsItems[this.Anim.steps - 1];
743 |
744 | if (action === 'plus' && this.Anim.steps < this.Anim.stepsMax) {
745 | this.Anim.steps++;
746 |
747 | division.nextSibling.classList.remove(this.Step.hiddenClass);
748 | this.paintShadow();
749 |
750 | if (this.Anim.steps === this.Anim.stepsMax) {
751 | elem.classList.add(this.Step.disabledClass);
752 | }
753 | else if (this.Anim.steps === 2) {
754 | this.enableControls();
755 | }
756 | }
757 | else if (action === 'minus' && this.Anim.steps > 1) {
758 | this.Anim.steps--;
759 | division.classList.add(this.Step.hiddenClass);
760 | this.paintShadow();
761 |
762 | if (this.Anim.steps === this.currentFrame) {
763 | this.currentFrame--;
764 | var prevInput = document.querySelectorAll(checkClassDot(this.Step.inputClass))[this.currentFrame];
765 | prevInput.checked = true;
766 | }
767 |
768 | if (this.Anim.steps === 1) {
769 | elem.classList.add(this.Step.disabledClass);
770 | }
771 | else if (this.Anim.steps === this.Anim.stepsMax - 1) {
772 | this.enableControls();
773 | }
774 | }
775 | };
776 |
777 | // -----------------------------------------
778 |
779 | ShadowPainter.prototype.enableControls = function () {
780 | var disabledItem = document.querySelector(checkClassDot(this.Step.disabledClass));
781 | if (disabledItem) {
782 | disabledItem.classList.remove(this.Step.disabledClass);
783 | }
784 | };
785 |
786 | // -----------------------------------------
787 |
788 | ShadowPainter.prototype.onClickClearFrames = function (elem) {
789 | var action = elem.getAttribute('data-action');
790 |
791 | if (action === 'all') {
792 | this.createFramesSet();
793 | this.paintShadow();
794 | this.updateCells();
795 | }
796 | else {
797 | this.resetCurrentFrame();
798 | this.paintShadow();
799 | this.updateCells();
800 | }
801 | };
802 |
803 | // -----------------------------------------
804 |
805 | ShadowPainter.prototype.updateSteps = function () {
806 | var radio = this.Elems.steps.querySelectorAll('input');
807 |
808 | for (var i = 0; i < radio.length; i++) {
809 | if (this.Frames[i].active > 0) {
810 | radio[i].classList.add('is--filled');
811 | }
812 | else {
813 | radio[i].classList.remove('is--filled');
814 | }
815 | }
816 | };
817 |
818 | // -----------------------------------------
819 |
820 | ShadowPainter.prototype.updateCells = function () {
821 | var checkboxes = this.Elems.paintBox.querySelectorAll('input');
822 | var frameCells = this.Frames[this.currentFrame];
823 | var colored = 0;
824 |
825 | for (var i = 0; i < checkboxes.length; i++) {
826 | var cell = checkboxes[i];
827 | var hpos = cell.getAttribute('data-hpos');
828 | var vpos = cell.getAttribute('data-vpos');
829 | var color = frameCells[hpos][vpos].color;
830 |
831 | if (color === this.Colors.transparent) {
832 | cell.checked = false;
833 | }
834 | else {
835 | colored++;
836 | cell.checked = true;
837 | }
838 | }
839 | };
840 |
841 | // -----------------------------------------
842 |
843 | ShadowPainter.prototype.createCodes = function () {
844 | this.addEvents(this.classNames.codesToggle, this.onClickCodes);
845 | };
846 |
847 | // -----------------------------------------
848 |
849 | ShadowPainter.prototype.onClickCodes = function () {
850 | var textInit = this.Elems.codesToggle.getAttribute('data-init');
851 | var textClose = this.Elems.codesToggle.getAttribute('data-opened');
852 | var text = textInit;
853 |
854 | if (this.isCodeOpened) {
855 | this.isCodeOpened = false;
856 | }
857 | else {
858 | this.isCodeOpened = true;
859 | text = textClose;
860 | }
861 |
862 | this.Elems.codesToggle.innerHTML = text;
863 | this.Elems.codes.classList.toggle('is-open');
864 |
865 | this.Output.HTML = `\n
`;
866 |
867 | this.Elems.codesCSS.innerHTML = `/*-- ${this.Output.comment} */\n${this.createOutputCSS()}`;
868 | this.Elems.codesHtml.innerHTML = this.Output.HTML;
869 | };
870 |
871 | // -----------------------------------------
872 |
873 | ShadowPainter.prototype.createOutputCSS = function () {
874 | var styles = '';
875 | var dottes = this.Frames[0];
876 | var shadows = this.createShadow(dottes, true);
877 |
878 | this.setOutputParams();
879 | this.outputElemParams['.dot']['box-shadow'] = shadows;
880 |
881 | for (var elem in this.outputElemParams) {
882 | var className = elem;
883 | var elemStyles = '';
884 | var params = this.outputElemParams[elem];
885 | for (var item in params) {
886 | var value = addUnits(params[item], item);
887 | elemStyles += item + ': ' + value + ';\n';
888 | }
889 | styles += `${className} {\n${elemStyles}}\n`;
890 | }
891 |
892 | styles += '\n/* Keyframes */\n';
893 |
894 | var animation = `@keyframes shadows {\n${this.Output.Animation}\n}\n`;
895 | styles += animation;
896 |
897 | return styles;
898 | };
899 |
900 | // -----------------------------------------
901 |
902 | ShadowPainter.prototype.createDurationInp = function () {
903 | var durationInt = this.Anim.duration.split('s').join('');
904 | this.Elems.durationInp.value = durationInt;
905 |
906 | this.addDataDefautlt(this.Elems.durationInp, durationInt);
907 | this.addOnChangeEvents(this.classNames.durationInp, this.onChangeDuration);
908 | };
909 |
910 | // -----------------------------------------
911 |
912 | ShadowPainter.prototype.onChangeDuration = function (elem) {
913 | this.Anim.duration = elem.value + 's';
914 | this.paintShadow();
915 | };
916 |
917 | // -----------------------------------------
918 |
919 | ShadowPainter.prototype.createSizeInp = function () {
920 | this.Elems.sizeInp.value = this.Scene.size;
921 |
922 | this.addDataDefautlt(this.Elems.sizeInp, this.Scene.size);
923 | this.addOnChangeEvents(this.classNames.sizeInp, this.onChangeSize);
924 | };
925 |
926 | // -----------------------------------------
927 |
928 | ShadowPainter.prototype.onChangeSize = function (elem) {
929 | this.Scene.size = Number(elem.value);
930 |
931 | this.addConfig();
932 | this.paintShadow();
933 | };
934 |
935 | ShadowPainter.prototype.onChangeDots = function (elem) {
936 | this.Scene.oneSide = Number(elem.value);
937 |
938 | this.addConfig();
939 | this.createInputsSet();
940 | this.paintShadow();
941 | };
942 |
943 | // -----------------------------------------
944 |
945 | ShadowPainter.prototype.createDotsInp = function () {
946 | this.Elems.dotsInp.value = this.Scene.oneSide;
947 |
948 | this.addDataDefautlt(this.Elems.dotsInp, this.Scene.oneSide);
949 | this.addOnChangeEvents(this.classNames.dotsInp, this.onChangeDots);
950 | };
951 |
952 | // -----------------------------------------
953 |
954 | ShadowPainter.prototype.initColors = function() {
955 | const colors = {
956 | className: 'color',
957 | inputType: 'radio',
958 | inputClass: 'color__inp',
959 | inputData: 'data-color="{color}" ',
960 |
961 | labelContent: '',
962 | controlClass: 'colors-controls__item',
963 | transparent: 'rgba(255,255,255,0)',
964 | currentNum: 0,
965 | currentListNum: 0
966 | };
967 |
968 | colors.list = this.Palettes[colors.currentListNum];
969 |
970 | colors.current = colors.list[0];
971 | colors.classCurrent = `${colors.className}--${colors.currentNum}`;
972 |
973 | colors.StyleTempl = `.${colors.className}--{i} {background: {color};}\n`;
974 | colors.controlTempl = '';
975 |
976 | colors.upDown = {
977 | list: {
978 | 'up': '',
979 | 'down': ''
980 | },
981 | replacements: {
982 | '{itemsClass}': colors.controlClass
983 | },
984 | template: ''
985 | };
986 |
987 | return colors;
988 | };
989 |
990 | // -----------------------------------------
991 |
992 | ShadowPainter.prototype.initStep = function() {
993 | const step = {
994 | className: 'step',
995 | inputType: 'radio',
996 | inputClass: 'step__inp',
997 | inputData: '',
998 | labelContent: '{i+1}',
999 | controlClass: 'steps-control',
1000 | clearFramesClass: 'frames-clear',
1001 |
1002 | currentNum: 0,
1003 | customClass: '{customClass}',
1004 | hiddenClass: 'is-hidden',
1005 | disabledClass: 'is-disabled'
1006 | };
1007 | step.plusMinus = {
1008 | list: {
1009 | 'minus': '–',
1010 | 'plus': '+'
1011 | },
1012 | replacements: {
1013 | '{itemsClass}': step.controlClass
1014 | },
1015 | template: '{text}',
1016 | insertBetween: 'this.Frames'
1017 | };
1018 |
1019 | step.clearFrames = {
1020 | list: {
1021 | 'current': 'Clear current frame',
1022 | 'all': 'Clear all frames'
1023 | },
1024 | replacements: {
1025 | '{itemsClass}': step.clearFramesClass
1026 | },
1027 | template: '{text}'
1028 | };
1029 |
1030 | return step;
1031 | };
1032 |
1033 | // Helpers
1034 | // -----------------------------------------
1035 |
1036 | function out(data, is_style, color) {
1037 | var style;
1038 |
1039 | if (is_style) {
1040 | color = color || 'orangered';
1041 | style = 'color: ' + color + '; padding-left: 20px;';
1042 | style = `color: ${color}; padding-left: 20px;`;
1043 | data = `%c${data}`;
1044 | console.log(data, style);
1045 | }
1046 | else {
1047 | console.log(data);
1048 | }
1049 | }
1050 |
1051 | // -----------------------------------------
1052 |
1053 | function addStylesElem(elemClass) {
1054 | var elem = document.createElement('style');
1055 | elem.classList.add(elemClass);
1056 | var head = document.querySelector('head');
1057 | head.appendChild(elem);
1058 | return elem;
1059 | }
1060 |
1061 | // -----------------------------------------
1062 |
1063 | function findKeyFrames(name) {
1064 | var keyFrames;
1065 | var sheets = document.styleSheets;
1066 |
1067 | for (var i = 0; i < sheets.length; i++) {
1068 | try {
1069 | var stylesList = sheets[i].cssRules;
1070 |
1071 | for (var k = 0; k < stylesList.length; k++) {
1072 | if (stylesList[k].name === name) {
1073 | keyFrames = stylesList[k];
1074 | }
1075 | }
1076 | }
1077 | catch {}
1078 |
1079 | }
1080 |
1081 | return keyFrames;
1082 | }
1083 |
1084 | // -----------------------------------------
1085 |
1086 | function checkClassDot(className) {
1087 | if (className.indexOf('.') < 0) {
1088 | className = '.' + className;
1089 | }
1090 | return className;
1091 | }
1092 |
1093 | // -----------------------------------------
1094 |
1095 | function strIsNAN(str) {
1096 | str = str.replace(/-|\./g,'');
1097 | str = str.split(' ').join('');
1098 | return isNaN(str);
1099 | }
1100 |
1101 | // -----------------------------------------
1102 |
1103 | function addUnits(str) {
1104 | str = String(str);
1105 | var arr = str.split(' ');
1106 |
1107 | if (strIsNAN(str)) {
1108 | return str;
1109 | }
1110 |
1111 | if (arr.length > 1 &&
1112 | arr[0].indexOf('px') < 0 &&
1113 | arr[0].indexOf('em') < 0 &&
1114 | arr[0].indexOf('%') < 0) {
1115 | str = arr.join('px ') + 'px';
1116 | return str;
1117 | }
1118 |
1119 | if (str.indexOf('px') < 0 &&
1120 | str.indexOf('em') < 0 &&
1121 | arr[0].indexOf('%') < 0) {
1122 | str += 'px';
1123 | }
1124 |
1125 | return str;
1126 | }
1127 |
1128 | // -----------------------------------------
1129 |
1130 | function getValByKeyCode(elem, key, isShift) {
1131 | var value = Number(elem.value);
1132 | var min = elem.getAttribute('data-min');
1133 | var max = elem.getAttribute('data-max');
1134 |
1135 | var step = isShift ? 10 : 1;
1136 |
1137 | if (key === 38) {
1138 | if (value >= 0 &&
1139 | value < 1 &&
1140 | min < 1) {
1141 |
1142 | step = 0.1;
1143 | }
1144 | value += step;
1145 | }
1146 | else if (key === 40) {
1147 | if (value > 0 &&
1148 | value <= 1 &&
1149 | min < 1) {
1150 |
1151 | step = 0.1;
1152 | }
1153 | value -= step;
1154 | }
1155 |
1156 | if (value < min) {
1157 | value = min;
1158 | }
1159 | else if (max !== null && value > max) {
1160 | value = max;
1161 | }
1162 | else {
1163 | if (value > 0 && value < 1) {
1164 | value = value.toFixed(1);
1165 | }
1166 | else {
1167 | value = value.toFixed();
1168 | }
1169 | }
1170 |
1171 | return value;
1172 | }
1173 |
1174 | // -----------------------------------------
1175 |
1176 | function valueSetDefaultIfNAN(elem) {
1177 | var value = elem.value;
1178 | var defaultValue = elem.getAttribute('data-default');
1179 | if (isNaN(value)) {
1180 | return defaultValue;
1181 | }
1182 |
1183 | return false;
1184 | }
1185 |
1186 | // -----------------------------------------
1187 |
1188 | function minMaxDef(elem) {
1189 | var min = elem.getAttribute('data-min');
1190 | min = min === null ? 0 : Number(min);
1191 |
1192 | var max = elem.getAttribute('data-max');
1193 | max = max === null ? 100 : Number(max);
1194 |
1195 | var value = elem.value;
1196 |
1197 | var out = value > max ? max : value < min ? min : false;
1198 | return out;
1199 | }
1200 |
1201 | // -----------------------------------------
1202 |
1203 | function createTemplate(item) {
1204 | var itemType = item.className;
1205 | var inputType = item.inputType;
1206 | var data_attr = item.inputData;
1207 | var lblContent = item.labelContent;
1208 | var itemCustomClass = item.customClass ? item.customClass : '';
1209 |
1210 | var itemInpClass = itemType + '__inp';
1211 | var itemLblClass = itemType + '__lbl';
1212 |
1213 | var replacements = {
1214 | '{inputType}': inputType,
1215 | '{itemType}': itemType,
1216 | '{itemClass}': itemType,
1217 | '{itemLblClass}': itemLblClass,
1218 | '{itemInpClass}': itemInpClass,
1219 | '{lblContent}': lblContent
1220 | };
1221 |
1222 | var itemInputTempl = ``;//
1223 | var itemLabelTempl = ``;
1224 | var itemTempl = `${itemInputTempl}${itemLabelTempl}`;
1225 |
1226 | var result = fillTemplate(itemTempl, replacements);
1227 |
1228 | return result;
1229 | }
1230 |
1231 | // -----------------------------------------
1232 |
1233 | function fillTemplate(dataStr, replacements) {
1234 | for (var key in replacements) {
1235 | var findStr = key;
1236 | var replaceWithStr = replacements[key];
1237 |
1238 | dataStr = dataStr.split(findStr).join(replaceWithStr);
1239 | }
1240 | return dataStr;
1241 | }
1242 |
1243 | // -----------------------------------------
1244 |
1245 | function objLength(obj) {
1246 | var count = 0;
1247 | for (var key in obj) {
1248 | count++;
1249 | }
1250 | return count;
1251 | }
1252 |
1253 | // Init
1254 | // -----------------------------------------
1255 |
1256 | var painter = new ShadowPainter();
1257 |
1258 | painter.init();
1259 |
1260 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | let sync = require('browser-sync').create();
3 | var reload = sync.reload;
4 | var include = require('gulp-include');
5 | var sass = require('gulp-sass');
6 | var postcss = require('gulp-postcss');
7 | var autoprefixer = require('autoprefixer');
8 | var cssnano = require('cssnano');
9 | var rename = require('gulp-rename');
10 | var mqpacker = require('css-mqpacker');
11 | var copy = require('gulp-copy');
12 | var ghPages = require('gulp-gh-pages');
13 | var colors = require('colors/safe');
14 | var del = require('del');
15 |
16 | sass.compiler = require('node-sass');
17 |
18 | // SASS, AUTOPREFIXR, MINIMIZE
19 | gulp.task('sass', function () {
20 | var processors = [
21 | autoprefixer({browsers: [
22 | 'last 1 version',
23 | 'last 2 Chrome versions',
24 | 'last 2 Firefox versions',
25 | 'last 2 Opera versions',
26 | 'last 2 Edge versions'
27 | ]}),
28 | mqpacker()
29 | ];
30 |
31 | console.log('⬤ Run ' + colors.yellow('Sass') +
32 | ' + ' +
33 | colors.green('Autoprefixer') +
34 | ' + ' +
35 | colors.cyan('Cssnano') + ' ⬤'
36 | );
37 |
38 | return gulp.src('src/scss/styles.scss')
39 | .pipe(sass().on('error', sass.logError))
40 | .pipe(postcss(processors))
41 | .pipe(gulp.dest('./assets/css'))
42 | .pipe(sync.stream())
43 | .pipe(postcss([cssnano()]))
44 | .pipe(rename('styles.min.css'))
45 | .pipe(gulp.dest('assets/css'));
46 | });
47 |
48 | // JS
49 | gulp.task('js', function () {
50 | return gulp.src('src/js/**/*.js')
51 | .pipe(gulp.dest('assets/js/'))
52 | .pipe(reload({stream: true}));
53 | });
54 |
55 | // INCLUDE BLOCKS IN HTML
56 | gulp.task('include', function () {
57 | console.log(colors.blue('⬤ Include files to HTML... ⬤'));
58 |
59 | gulp.src('src/index.html')
60 | .pipe(include())
61 | .on('error', console.log)
62 | .pipe(gulp.dest('.'))
63 | .pipe(reload({stream: true}));
64 | });
65 |
66 | // WATCH SASS, PREPROCESS AND RELOAD
67 | gulp.task('serve', gulp.series('sass', function () {
68 | sync.init({
69 | ui: false,
70 | notify: false,
71 | port: 3000,
72 | server: {
73 | baseDir: '.'
74 | }
75 | });
76 |
77 | gulp.watch(['src/**/*.scss'], gulp.series('sass'));
78 | gulp.watch(['src/**/*.html'], gulp.series('include'));
79 | gulp.watch(['src/**/*.js'], gulp.series('js'));
80 | }));
81 |
82 | // CLEAN BUILD
83 | gulp.task('clean', function () {
84 | del(['build/*']).then(paths => {
85 | console.log('⬤ Deleted files and folders:\n', paths.join('\n'));
86 | });
87 | });
88 |
89 | // CLEAN BUILD & COPY FILES TO IT
90 | gulp.task('copy', function () {
91 | console.log(colors.magenta('⬤ Clear build/ and copy files to it... ⬤'));
92 |
93 | return gulp.src(['assets/**/*', '*.html'])
94 | .pipe(copy('build/'));
95 | });
96 |
97 | // PUBLISH TO GITHUB PAGES
98 | gulp.task('ghPages', function () {
99 | console.log(colors.rainbow('⬤ Publish to Github Pages... ⬤'));
100 |
101 | return gulp.src('build/**/*')
102 | .pipe(ghPages());
103 | });
104 |
105 | gulp.task('default', function () {
106 | console.log(colors.rainbow('⬤ ================================ ⬤\n'));
107 | console.log(' AVAILABLE COMMANDS:');
108 | console.log(' ' + colors.cyan('-------------------\n'));
109 | console.log(' ' + colors.yellow('npm start') +
110 | ' — run local server with watcher');
111 | console.log(' ' + colors.green('npm run build') +
112 | ' — make build of the project');
113 | console.log(' ' + colors.cyan('npm run deploy') +
114 | ' — make build and publish project to Github Pages');
115 | console.log(colors.rainbow('\n⬤ ================================ ⬤'));
116 | });
117 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Create shadow animation
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Duration
13 | sec.
14 |
Dotts
15 |
16 |
Size
17 | px
18 |
19 |
25 |
28 |
29 |
Get codes
30 |
31 |
CSS
32 |
33 | HTML
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shadowPainter",
3 | "version": "0.0.1",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "gulp serve",
8 | "img": "gulp images",
9 | "build": "gulp clean && gulp sass && gulp include && gulp copy",
10 | "deploy": "npm run build && gulp ghPages",
11 | "js:lint": "eslint '**/*.js'",
12 | "js:fix": "eslint '**/*.js' --fix",
13 | "css:lint": "stylelint src/**/*.scss",
14 | "lint": "npm run js:lint && npm run css:lint",
15 | "lint:fix": "npm run js:fix"
16 | },
17 | "author": "yoksel",
18 | "license": "ISC",
19 | "devDependencies": {
20 | "autoprefixer": "^6.3.5",
21 | "babel-eslint": "^10.0.1",
22 | "browser-sync": "^2.26.3",
23 | "colors": "^1.1.2",
24 | "css-mqpacker": "^4.0.1",
25 | "cssnano": "^4.1.10",
26 | "del": "^2.2.0",
27 | "eslint": "^5.12.1",
28 | "eslint-config-yandex": "^1.0.6",
29 | "eslint-plugin-babel": "^5.3.0",
30 | "gulp": "^4.0.0",
31 | "gulp-copy": "0.0.2",
32 | "gulp-gh-pages": "^0.5.4",
33 | "gulp-include": "^2.1.0",
34 | "gulp-postcss": "^6.1.0",
35 | "gulp-rename": "^1.2.2",
36 | "gulp-sass": "^4.0.2",
37 | "stylelint": "^9.10.1",
38 | "stylelint-config-standard": "^18.2.0"
39 | },
40 | "dependencies": {}
41 | }
42 |
--------------------------------------------------------------------------------
/src/js/script.js:
--------------------------------------------------------------------------------
1 | var line = '------------------------';
2 |
3 | function ShadowPainter() {
4 | this.timer;
5 | this.isMousePressed = false;
6 |
7 | this.classNames = {
8 | wrapper: '.l-wrapper',
9 | paintBox: '.b-box--paint',
10 | resultBox: '.b-box--result',
11 | resultDot: '.b-box--result .dot',
12 | palette: '.b-palette',
13 | steps: '.b-steps',
14 |
15 | codes: '.b-codes',
16 | codesToggle: '.b-codes__toggle',
17 | codesCSS: '.textarea--css',
18 | codesHtml: '.textarea--html',
19 |
20 | durationInp: '.text--duration',
21 | sizeInp: '.text--size',
22 | dotsInp: '.text--dots',
23 | isRunning: 'is-running',
24 | };
25 |
26 | this.Elems = {};
27 |
28 | this.Cell = {
29 | className: 'cell',
30 | inputType: 'checkbox',
31 | inputClass: 'cell__inp',
32 | labelClass: 'cell__lbl',
33 | inputData: 'data-hpos="{hpos}" data-vpos="{vpos}" ',
34 | labelContent: '',
35 | dots: ''
36 | };
37 |
38 | this.Palettes = [
39 | ['#3FB8AF','#7FC7AF','#DAD8A7','#FF9E9D','#FF3D7F'],
40 | ['#468966','#FFF0A5','#FFB03B','#B64926','#8E2800'],
41 | ['#004358','#1F8A70','#BEDB39','#FFE11A','#FD7400'],
42 | ['#96CA2D','#B5E655','#EDF7F2','#4BB5C1','#7FC6BC'],
43 | ['#2E0927','#D90000','#FF2D00','#FF8C00','#04756F'],
44 | ['#FCFFF5','#D1DBBD','#91AA9D','#3E606F','#193441'],
45 | ['#332532','#644D52','#F77A52','#FF974F','#A49A87']
46 | ];
47 |
48 | this.Colors = this.initColors();
49 | this.Step = this.initStep();
50 |
51 | this.stylesClassNames = {
52 | config: 'configBox',
53 | shadows: 'stylesBox',
54 | colors: 'colorsBox'
55 | };
56 | this.Styles = {};
57 |
58 | this.Output = {
59 | HTML: '',
60 | CSS: '',
61 | Animation: '',
62 | comment: 'Created in shadowPainter : )'
63 | };
64 |
65 | this.Scene = {
66 | oneSide: 5,// dottes in line
67 | oneSideMax: 30,// dottes in line
68 | size: 250,
69 | dotSize: 30,// pixels
70 | padding: 20,// pixels. Don't change it
71 | border: 1// pixels
72 | };
73 |
74 | this.Anim = {
75 | steps: 5,
76 | stepsMax: 20,
77 | duration: '1s',
78 | name: 'shadows',
79 | keyframes: findKeyFrames('shadows')
80 | };
81 | this.Anim.rules = this.Anim.keyframes.cssRules;
82 |
83 | this.isCodeOpened = false;
84 |
85 | this.Frames = {};
86 | this.currentFrame = 0;
87 |
88 | this.init = function () {
89 | this.createTemplates();
90 | this.createStylesBoxes();
91 |
92 | this.initElements();
93 | this.addConfig();
94 | this.createInputsSet();
95 | this.createFramesSet();
96 | this.createPalette();
97 | this.createSteps();
98 | this.createCodes();
99 | this.createDurationInp();
100 | this.createSizeInp();
101 | this.createDotsInp();
102 | };
103 |
104 | } // End ShadowPainter()
105 |
106 | // -----------------------------------------
107 |
108 | ShadowPainter.prototype.setTimer = function(func, params) {
109 | if (this.timer) {
110 | this.clearTimeout(this.timer);
111 | }
112 | var execFunc = function () {
113 | func(params);
114 | };
115 | this.timer = this.setTimeout(execFunc , 50);
116 | };
117 |
118 | // -----------------------------------------
119 |
120 | ShadowPainter.prototype.getAnimStr = function() {
121 | return `${this.Anim.duration} ${this.Anim.name} linear infinite`;
122 | };
123 |
124 | // -----------------------------------------
125 |
126 | ShadowPainter.prototype.initElements = function () {
127 | for (var className in this.classNames) {
128 | this.Elems[className] = document.querySelector(this.classNames[className]);
129 | }
130 | };
131 |
132 | // -----------------------------------------
133 |
134 | ShadowPainter.prototype.setParams = function () {
135 | let dotSize = (this.Scene.size / this.Scene.oneSide);
136 | this.Scene.dotSize = dotSize.toFixed();
137 | this.Scene.size = this.Scene.dotSize * this.Scene.oneSide;
138 |
139 | this.configElemParams = {
140 | '.l-wrapper': {
141 | 'width': 700, // size * 2 + this.Scene.padding * 3 + border*6
142 | 'height': 490, // size + this.Scene.padding * 2 + border*4
143 | },
144 | '.b-boxes': {
145 | 'height': 340
146 | },
147 | '.l-zero-gravity': {
148 | 'height': this.Scene.size + this.Scene.border
149 | },
150 | '.b-box': {
151 | 'width': this.Scene.size + this.Scene.border,
152 | 'height': this.Scene.size
153 | },
154 | '.cell__lbl': {
155 | 'width': this.Scene.dotSize,
156 | 'height': this.Scene.dotSize
157 | },
158 | '.dot': {
159 | 'width': this.Scene.dotSize,
160 | 'height': this.Scene.dotSize,
161 | 'top': '-' + this.Scene.dotSize,
162 | 'left': '-' + this.Scene.dotSize
163 | },
164 | '.is-running': {
165 | 'animation': this.getAnimStr()
166 | },
167 | '.b-box--paint': {
168 | 'background-size': this.Scene.dotSize + ' ' + this.Scene.dotSize
169 | }
170 | };
171 | };
172 |
173 | // -----------------------------------------
174 |
175 | ShadowPainter.prototype.setOutputParams = function () {
176 | this.outputElemParams = {
177 | '.box': {
178 | 'position': 'absolute',
179 | 'top': '0',
180 | 'bottom': '0',
181 | 'left': '0',
182 | 'right': '0',
183 | 'margin': 'auto',
184 | 'width': this.Scene.size,
185 | 'height': this.Scene.size,
186 | 'overflow': 'hidden',
187 | 'border': '1px solid #DDD'
188 | },
189 | '.dot': {
190 | 'display': 'block',
191 | 'position': 'absolute',
192 | 'width': this.Scene.dotSize,
193 | 'height': this.Scene.dotSize,
194 | 'top': '-' + this.Scene.dotSize,
195 | 'left': '-' + this.Scene.dotSize,
196 | 'animation': this.getAnimStr()
197 | }
198 | };
199 | };
200 |
201 | // -----------------------------------------
202 |
203 | ShadowPainter.prototype.addConfig = function () {
204 | this.setParams();
205 |
206 | var styles = '';
207 | for (var elem in this.configElemParams) {
208 | var className = elem;
209 | var elemStyles = '';
210 | var params = this.configElemParams[elem];
211 | for (var item in params) {
212 | var value = addUnits(params[item], item);
213 | elemStyles += item + ': ' + value + ';\n';
214 | }
215 | styles += className + ' {\n' + elemStyles + '}\n';
216 | }
217 |
218 | this.Styles.config.innerHTML = styles;
219 | };
220 |
221 | // -----------------------------------------
222 |
223 | ShadowPainter.prototype.createStylesBoxes = function () {
224 | for (var styleBox in this.stylesClassNames) {
225 | this.Styles[styleBox] = addStylesElem(this.stylesClassNames[styleBox]);
226 | }
227 | };
228 |
229 | // -----------------------------------------
230 |
231 | ShadowPainter.prototype.createTemplates = function () {
232 | var templatesConfig = [this.Cell, this.Colors, this.Step];
233 |
234 | for (var i = 0; i < templatesConfig.length; i++) {
235 | var item = templatesConfig[i];
236 | item.template = createTemplate(item);
237 | }
238 | };
239 |
240 | // -----------------------------------------
241 |
242 | ShadowPainter.prototype.createControls = function (data) {
243 | var output = '';
244 |
245 | var counter = 0;
246 | for (var item in data.list) {
247 | data.replacements['{action}'] = item;
248 | data.replacements['{text}'] = data.list[ item ];
249 | output += fillTemplate(data.template, data.replacements);
250 |
251 | if (counter === 0 && data.insertBetween) {
252 | output += data.insertBetween;
253 | }
254 | counter++;
255 | }
256 | return output;
257 | };
258 |
259 | // -----------------------------------------
260 |
261 | ShadowPainter.prototype.addDataDefautlt = function (elem, defaultValue) {
262 | var defData = elem.getAttribute('data-default');
263 |
264 | if (defData === null) {
265 | elem.setAttribute('data-default', defaultValue);
266 | }
267 | };
268 |
269 | // -----------------------------------------
270 |
271 | ShadowPainter.prototype.addEvents = function (itemsClass, func) {
272 | itemsClass = checkClassDot(itemsClass);
273 | var items = document.querySelectorAll(itemsClass);
274 | var parent = this;
275 |
276 | for (var i = 0; i < items.length; i++) {
277 | items[i].onclick = function () {
278 | func.call(parent, this);
279 | };
280 | }
281 | };
282 |
283 | // -----------------------------------------
284 |
285 | ShadowPainter.prototype.addOverEvents = function (itemsClass, func) {
286 | itemsClass = checkClassDot(itemsClass);
287 | var items = document.querySelectorAll(itemsClass);
288 | var parent = this;
289 |
290 | for (var i = 0; i < items.length; i++) {
291 | items[i].onmousedown = function () {
292 | this.isMousePressed = true;
293 | };
294 |
295 | items[i].onmouseup = function () {
296 | this.isMousePressed = false;
297 | };
298 |
299 | items[i].onmouseover = function () {
300 | if (this.isMousePressed) {
301 | func.call(parent, this);
302 | }
303 | };
304 | }
305 | };
306 |
307 | // -----------------------------------------
308 |
309 | ShadowPainter.prototype.checkInputValue = function (params) {
310 | var elem = params.elem;
311 | var func = params.func;
312 | var parent = params.parent;
313 |
314 | var minMax = minMaxDef(elem);
315 | var isNan = valueSetDefaultIfNAN(elem);
316 |
317 | if (isNan) {
318 | elem.value = isNan;
319 | }
320 |
321 | if (minMax) {
322 | elem.value = minMax;
323 | }
324 |
325 | func.call(parent, elem);
326 | };
327 |
328 | // -----------------------------------------
329 |
330 | ShadowPainter.prototype.addOnChangeEvents = function (itemsClass, func) {
331 | var items = document.querySelectorAll(itemsClass);
332 | var parent = this;
333 |
334 | var params = {
335 | func: func,
336 | parent: parent
337 | };
338 |
339 | for (var i = 0; i < items.length; i++) {
340 | items[i].onkeyup = function (event) {
341 | params.elem = this;
342 |
343 | if (event.keyCode === 38 || event.keyCode === 40) {
344 |
345 | this.value = getValByKeyCode(this, event.keyCode, event.shiftKey);
346 | func.call(parent, this);
347 | }
348 | else {
349 | this.setTimer(parent.checkInputValue, params);
350 | }
351 | };
352 |
353 | items[i].onchange = function () {
354 | params.elem = this;
355 | parent.checkInputValue(params);
356 | };
357 |
358 | items[i].onblur = function () {
359 | params.elem = this;
360 | parent.checkInputValue(params);
361 | };
362 | }
363 | };
364 |
365 | // -----------------------------------------
366 |
367 | ShadowPainter.prototype.createInputsSet = function () {
368 | this.Elems.paintBox.innerHTML = this.Cell.dots;
369 | var output = '';
370 |
371 | for (var i = 0; i < this.Scene.oneSide * this.Scene.oneSide; i++) {
372 | var hpos = i % this.Scene.oneSide + 1;
373 | var vpos = Math.floor(i / this.Scene.oneSide) + 1;
374 |
375 | var replacements = {
376 | '{i}': i,
377 | '{hpos}': hpos,
378 | '{vpos}': vpos
379 | };
380 | var checkBox = fillTemplate(this.Cell.template, replacements);
381 | output += checkBox;
382 | }
383 |
384 | this.Elems.paintBox.innerHTML += ``;
385 |
386 | this.addOverEvents(this.Cell.labelClass, this.onOverLabel);
387 | this.addEvents(this.Cell.inputClass, this.onClickCell);
388 | };
389 |
390 | // -----------------------------------------
391 |
392 | ShadowPainter.prototype.createFramesSet = function () {
393 | for (var k = 0; k < this.Anim.stepsMax; k++) {
394 | this.Frames[k] = {active: 0};
395 |
396 | for (var hpos = 0; hpos < this.Scene.oneSideMax; hpos++) { // verticals
397 | this.Frames[k][hpos] = {};
398 |
399 | for (var vpos = 0; vpos < this.Scene.oneSideMax; vpos++) { // gorizontals
400 |
401 | this.Frames[k][hpos][vpos] = {
402 | 'hpos': hpos,
403 | 'vpos': vpos,
404 | 'color': this.Colors.transparent
405 | };
406 | } // End gorizontals
407 | } // End verticals
408 | }
409 | };
410 |
411 | // -----------------------------------------
412 |
413 | ShadowPainter.prototype.resetCurrentFrame = function () {
414 | var k = this.currentFrame;
415 | this.Frames[k] = {active: 0};
416 |
417 | for (var hpos = 0; hpos < this.Scene.oneSideMax; hpos++) { // verticals
418 | this.Frames[k][hpos] = {};
419 |
420 | for (var vpos = 0; vpos < this.Scene.oneSideMax; vpos++) { // gorizontals
421 | this.Frames[k][hpos][vpos] = {
422 | 'color': this.Colors.transparent
423 | };
424 | } // End gorizontals
425 | } // End verticals
426 | };
427 |
428 | // -----------------------------------------
429 |
430 | ShadowPainter.prototype.toggleColorClass = function (elem) {
431 | var findClass = this.Colors.className + '--';
432 | var classes = elem.classList;
433 |
434 | for (var i = 0; i < classes.length; i++) {
435 |
436 | if (classes[i].indexOf(findClass) >= 0) {
437 | classes.remove(classes[i]);
438 | return;
439 | }
440 | }
441 |
442 | classes.add(findClass + this.Colors.currentNum);
443 | };
444 |
445 | // -----------------------------------------
446 |
447 | ShadowPainter.prototype.onClickCell = function (elem) {
448 | this.updateFrames(elem);
449 | };
450 |
451 | // -----------------------------------------
452 |
453 | ShadowPainter.prototype.onOverLabel = function (elem) {
454 | var input = elem.previousSibling;
455 |
456 | if (input.checked === true) {
457 | input.checked = false;
458 | }
459 | else {
460 | input.checked = true;
461 | }
462 |
463 | this.updateFrames(input);
464 | };
465 |
466 | // -----------------------------------------
467 |
468 | ShadowPainter.prototype.updateFrames = function (elem) {
469 | var hpos = elem.getAttribute('data-hpos');
470 | var vpos = elem.getAttribute('data-vpos');
471 |
472 | var place = this.Frames[this.currentFrame];
473 | var color = this.Colors.transparent;
474 |
475 | if (elem.checked) {
476 | color = this.Colors.current;
477 | place.active++;
478 | }
479 | else {
480 | place.active--;
481 | }
482 |
483 | place[hpos][vpos].color = color;
484 | this.paintShadow();
485 | };
486 |
487 | // -----------------------------------------
488 |
489 | ShadowPainter.prototype.paintShadow = function () {
490 | var styles = '';
491 | var framesLength = this.Anim.steps; // objLength(this.Frames);
492 | var perc = this.Anim.steps === 1 ? 0 : (100 / framesLength).toFixed(3);
493 | var dottes = this.Frames[this.currentFrame];
494 | var shadows = this.createShadow(dottes);
495 |
496 | styles = '.b-box--paint .dot {\n ' + shadows + ' \n}\n';
497 |
498 | dottes = this.Frames[0];
499 | shadows = this.createShadow(dottes);
500 | styles += this.classNames.resultDot + ' {\n ' + shadows + ' \nanimation-duration: ' + this.Anim.duration + ';\n}\n';
501 |
502 | if (this.currentFrame > 0) {
503 | dottes = this.Frames[this.currentFrame - 1];
504 | shadows = this.createShadow(dottes);
505 |
506 | styles += '.b-box--paint .dot--previous {\n ' + shadows + ' \n}\n';
507 | }
508 |
509 | this.Styles.shadows.innerHTML = styles;
510 |
511 | this.replaceAnimation({perc: perc});
512 | };
513 |
514 | // -----------------------------------------
515 |
516 | ShadowPainter.prototype.createShadow = function (dottes, is_value) {
517 | if (dottes === undefined) {
518 | return;
519 | }
520 |
521 | var shadows = '';
522 | var if_first = true;
523 |
524 | for (var hpos = 0; hpos < this.Scene.oneSide + 1; hpos++) {
525 | for (var vpos = 0; vpos < this.Scene.oneSide + 1; vpos++) {
526 | var dot = dottes[hpos][vpos];
527 |
528 | var hpos_px = dot.hpos * this.Scene.dotSize + 'px';
529 | var vpos_px = dot.vpos * this.Scene.dotSize + 'px';
530 | var color = this.Colors.transparent;
531 |
532 |
533 | if (dot.color !== this.Colors.transparent) {
534 | color = dot.color;
535 | }
536 |
537 | if (if_first) {
538 | if_first = false;
539 | }
540 | else {
541 | shadows += ', ';
542 | }
543 |
544 | shadows += hpos_px + ' ' + vpos_px + ' 0 0 ' + color;
545 | }
546 | }
547 |
548 | if (!is_value) {
549 | shadows = 'box-shadow: ' + shadows + ';';
550 | }
551 |
552 | return shadows;
553 | };
554 |
555 | // -----------------------------------------
556 |
557 | ShadowPainter.prototype.deleteKeyframes = function () {
558 | var rules = this.Anim.rules;
559 | var keyFrames = this.Anim.keyframes;
560 | const max = 1000;
561 | let counter = 0;
562 |
563 | while (keyFrames.cssRules.length > 0 && counter < max) {
564 | const {keyText} = keyFrames.cssRules[0];
565 | keyFrames.deleteRule(keyText);
566 |
567 | counter++;
568 | }
569 | };
570 |
571 | // -----------------------------------------
572 |
573 | ShadowPainter.prototype.replaceAnimation = function (animation) {
574 | this.Output.Animation = '';
575 | this.deleteKeyframes();
576 |
577 | if (this.Anim.steps === 1) {
578 | this.restartAnimation();
579 | return;
580 | }
581 |
582 | for (var step = 0; step < this.Anim.steps; step++) {
583 | var anim_dottes = this.Frames[step];
584 | var anim_shadows = this.createShadow(anim_dottes);
585 | var stepPercents = +(animation.perc * step).toFixed(3);
586 | var frameRule = `${stepPercents}% {\n${anim_shadows}\n}`;
587 |
588 | this.Anim.keyframes.appendRule(frameRule);
589 | this.Output.Animation += frameRule + '\n';
590 | }
591 |
592 | this.restartAnimation();
593 | };
594 |
595 | // -----------------------------------------
596 |
597 | ShadowPainter.prototype.restartAnimation = function () {
598 | var resultDot = document.querySelector(this.classNames.resultDot);
599 | resultDot.classList.remove(this.classNames.isRunning);
600 | resultDot.classList.add(this.classNames.isRunning);
601 | };
602 |
603 | // -----------------------------------------
604 |
605 | ShadowPainter.prototype.createPalette = function () {
606 | const paletteControls = this.createControls(this.Colors.upDown);
607 | this.Elems.palette.innerHTML += 'Colors
';
608 | this.Elems.palette.innerHTML += '';
609 | this.Elems.palette.innerHTML += ``;
610 |
611 | this.fillPalette();
612 | this.addEvents(this.Colors.inputClass, this.onClickColor);
613 |
614 | var first = document.querySelector(checkClassDot(this.Colors.inputClass));
615 | first.checked = true;
616 |
617 | this.addEvents(this.Colors.controlClass, this.onClickColorControl);
618 | };
619 |
620 | // -----------------------------------------
621 |
622 | ShadowPainter.prototype.fillPalette = function () {
623 | var output = '';
624 | var colorsItems = document.querySelector('.items--colors');
625 | this.Styles.colors.innerHTML = '';
626 |
627 | for (var i = 0; i < this.Colors.list.length; i++) {
628 | var replacements = {
629 | '{i}': i,
630 | '{color}': this.Colors.list[i]
631 | };
632 | var colorItem = fillTemplate(this.Colors.template, replacements);
633 | var colorStyle = fillTemplate(this.Colors.StyleTempl, replacements);
634 | this.Styles.colors.innerHTML += colorStyle;
635 | output += colorItem;
636 | }
637 |
638 | colorsItems.innerHTML = output;
639 | };
640 |
641 | // -----------------------------------------
642 |
643 | ShadowPainter.prototype.reFillPalette = function () {
644 | var colorsItems = document.querySelectorAll(checkClassDot(this.Colors.inputClass));
645 | this.Styles.colors.innerHTML = '';
646 |
647 | for (var i = 0; i < this.Colors.list.length; i++) {
648 | colorsItems[i].setAttribute('data-color', this.Colors.list[i]);
649 | var replacements = {
650 | '{i}': i,
651 | '{color}': this.Colors.list[i]
652 | };
653 | var colorStyle = fillTemplate(this.Colors.StyleTempl, replacements);
654 |
655 | this.Styles.colors.innerHTML += colorStyle;
656 | }
657 | };
658 |
659 | // -----------------------------------------
660 |
661 | ShadowPainter.prototype.onClickColor = function (elem) {
662 | this.Colors.current = elem.getAttribute('data-color');
663 | this.Colors.currentNum = elem.getAttribute('data-color-num');
664 | this.Colors.classCurrent = this.Colors.className + '--' + this.Colors.currentNum;
665 | };
666 |
667 | // -----------------------------------------
668 |
669 | ShadowPainter.prototype.onClickColorControl = function (elem) {
670 | var direct = elem.getAttribute('data-direction');
671 | var max = this.Palettes.length - 1;
672 |
673 | if (direct === 'up') {
674 | if (this.Colors.currentListNum < max) {
675 | this.Colors.currentListNum++;
676 | }
677 | else {
678 | this.Colors.currentListNum = 0;
679 | }
680 | }
681 | else {
682 | if (this.Colors.currentListNum > 0) {
683 | this.Colors.currentListNum--;
684 | }
685 | else {
686 | this.Colors.currentListNum = max;
687 | }
688 | }
689 |
690 | this.Colors.list = this.Palettes[this.Colors.currentListNum];
691 | this.Colors.current = this.Colors.list[this.Colors.currentNum];
692 | this.Colors.classCurrent = this.Colors.className + '--' + this.Colors.currentNum;
693 |
694 | this.reFillPalette();
695 | };
696 |
697 | // -----------------------------------------
698 |
699 | ShadowPainter.prototype.createSteps = function () {
700 | var output = '';
701 | const plusMinusControls = this.createControls(this.Step.plusMinus);
702 | this.Elems.steps.innerHTML += `${plusMinusControls}
`;
703 |
704 | for (var i = 0; i < this.Anim.stepsMax; i++) {
705 | var customClass = i < this.Anim.steps ? '' : ' ' + this.Step.hiddenClass;
706 |
707 | var replacements = {
708 | '{i}': i,
709 | '{i+1}': i+1,
710 | '{customClass}': customClass
711 | };
712 |
713 | var stepItem = fillTemplate(this.Step.template, replacements);
714 | output += stepItem;
715 | }
716 |
717 | this.Elems.steps.innerHTML += ``;
718 |
719 | this.Elems.steps.innerHTML += this.createControls(this.Step.clearFrames);
720 |
721 | var first = document.querySelector(checkClassDot(this.Step.inputClass));
722 | first.checked = true;
723 |
724 | this.addEvents(this.Step.inputClass, this.onClickStep);
725 | this.addEvents(this.Step.controlClass, this.onClickStepControl);
726 | this.addEvents(this.Step.clearFramesClass, this.onClickClearFrames);
727 | };
728 |
729 | // -----------------------------------------
730 |
731 | ShadowPainter.prototype.onClickStep = function (elem) {
732 | this.currentFrame = elem.getAttribute('data-step-num');
733 | this.paintShadow();
734 | this.updateCells();
735 | };
736 |
737 | // -----------------------------------------
738 |
739 | ShadowPainter.prototype.onClickStepControl = function (elem) {
740 | var action = elem.getAttribute('data-action');
741 | var stepsItems = document.querySelectorAll(checkClassDot(this.Step.className));
742 | var division = stepsItems[this.Anim.steps - 1];
743 |
744 | if (action === 'plus' && this.Anim.steps < this.Anim.stepsMax) {
745 | this.Anim.steps++;
746 |
747 | division.nextSibling.classList.remove(this.Step.hiddenClass);
748 | this.paintShadow();
749 |
750 | if (this.Anim.steps === this.Anim.stepsMax) {
751 | elem.classList.add(this.Step.disabledClass);
752 | }
753 | else if (this.Anim.steps === 2) {
754 | this.enableControls();
755 | }
756 | }
757 | else if (action === 'minus' && this.Anim.steps > 1) {
758 | this.Anim.steps--;
759 | division.classList.add(this.Step.hiddenClass);
760 | this.paintShadow();
761 |
762 | if (this.Anim.steps === this.currentFrame) {
763 | this.currentFrame--;
764 | var prevInput = document.querySelectorAll(checkClassDot(this.Step.inputClass))[this.currentFrame];
765 | prevInput.checked = true;
766 | }
767 |
768 | if (this.Anim.steps === 1) {
769 | elem.classList.add(this.Step.disabledClass);
770 | }
771 | else if (this.Anim.steps === this.Anim.stepsMax - 1) {
772 | this.enableControls();
773 | }
774 | }
775 | };
776 |
777 | // -----------------------------------------
778 |
779 | ShadowPainter.prototype.enableControls = function () {
780 | var disabledItem = document.querySelector(checkClassDot(this.Step.disabledClass));
781 | if (disabledItem) {
782 | disabledItem.classList.remove(this.Step.disabledClass);
783 | }
784 | };
785 |
786 | // -----------------------------------------
787 |
788 | ShadowPainter.prototype.onClickClearFrames = function (elem) {
789 | var action = elem.getAttribute('data-action');
790 |
791 | if (action === 'all') {
792 | this.createFramesSet();
793 | this.paintShadow();
794 | this.updateCells();
795 | }
796 | else {
797 | this.resetCurrentFrame();
798 | this.paintShadow();
799 | this.updateCells();
800 | }
801 | };
802 |
803 | // -----------------------------------------
804 |
805 | ShadowPainter.prototype.updateSteps = function () {
806 | var radio = this.Elems.steps.querySelectorAll('input');
807 |
808 | for (var i = 0; i < radio.length; i++) {
809 | if (this.Frames[i].active > 0) {
810 | radio[i].classList.add('is--filled');
811 | }
812 | else {
813 | radio[i].classList.remove('is--filled');
814 | }
815 | }
816 | };
817 |
818 | // -----------------------------------------
819 |
820 | ShadowPainter.prototype.updateCells = function () {
821 | var checkboxes = this.Elems.paintBox.querySelectorAll('input');
822 | var frameCells = this.Frames[this.currentFrame];
823 | var colored = 0;
824 |
825 | for (var i = 0; i < checkboxes.length; i++) {
826 | var cell = checkboxes[i];
827 | var hpos = cell.getAttribute('data-hpos');
828 | var vpos = cell.getAttribute('data-vpos');
829 | var color = frameCells[hpos][vpos].color;
830 |
831 | if (color === this.Colors.transparent) {
832 | cell.checked = false;
833 | }
834 | else {
835 | colored++;
836 | cell.checked = true;
837 | }
838 | }
839 | };
840 |
841 | // -----------------------------------------
842 |
843 | ShadowPainter.prototype.createCodes = function () {
844 | this.addEvents(this.classNames.codesToggle, this.onClickCodes);
845 | };
846 |
847 | // -----------------------------------------
848 |
849 | ShadowPainter.prototype.onClickCodes = function () {
850 | var textInit = this.Elems.codesToggle.getAttribute('data-init');
851 | var textClose = this.Elems.codesToggle.getAttribute('data-opened');
852 | var text = textInit;
853 |
854 | if (this.isCodeOpened) {
855 | this.isCodeOpened = false;
856 | }
857 | else {
858 | this.isCodeOpened = true;
859 | text = textClose;
860 | }
861 |
862 | this.Elems.codesToggle.innerHTML = text;
863 | this.Elems.codes.classList.toggle('is-open');
864 |
865 | this.Output.HTML = `\n
`;
866 |
867 | this.Elems.codesCSS.innerHTML = `/*-- ${this.Output.comment} */\n${this.createOutputCSS()}`;
868 | this.Elems.codesHtml.innerHTML = this.Output.HTML;
869 | };
870 |
871 | // -----------------------------------------
872 |
873 | ShadowPainter.prototype.createOutputCSS = function () {
874 | var styles = '';
875 | var dottes = this.Frames[0];
876 | var shadows = this.createShadow(dottes, true);
877 |
878 | this.setOutputParams();
879 | this.outputElemParams['.dot']['box-shadow'] = shadows;
880 |
881 | for (var elem in this.outputElemParams) {
882 | var className = elem;
883 | var elemStyles = '';
884 | var params = this.outputElemParams[elem];
885 | for (var item in params) {
886 | var value = addUnits(params[item], item);
887 | elemStyles += item + ': ' + value + ';\n';
888 | }
889 | styles += `${className} {\n${elemStyles}}\n`;
890 | }
891 |
892 | styles += '\n/* Keyframes */\n';
893 |
894 | var animation = `@keyframes shadows {\n${this.Output.Animation}\n}\n`;
895 | styles += animation;
896 |
897 | return styles;
898 | };
899 |
900 | // -----------------------------------------
901 |
902 | ShadowPainter.prototype.createDurationInp = function () {
903 | var durationInt = this.Anim.duration.split('s').join('');
904 | this.Elems.durationInp.value = durationInt;
905 |
906 | this.addDataDefautlt(this.Elems.durationInp, durationInt);
907 | this.addOnChangeEvents(this.classNames.durationInp, this.onChangeDuration);
908 | };
909 |
910 | // -----------------------------------------
911 |
912 | ShadowPainter.prototype.onChangeDuration = function (elem) {
913 | this.Anim.duration = elem.value + 's';
914 | this.paintShadow();
915 | };
916 |
917 | // -----------------------------------------
918 |
919 | ShadowPainter.prototype.createSizeInp = function () {
920 | this.Elems.sizeInp.value = this.Scene.size;
921 |
922 | this.addDataDefautlt(this.Elems.sizeInp, this.Scene.size);
923 | this.addOnChangeEvents(this.classNames.sizeInp, this.onChangeSize);
924 | };
925 |
926 | // -----------------------------------------
927 |
928 | ShadowPainter.prototype.onChangeSize = function (elem) {
929 | this.Scene.size = Number(elem.value);
930 |
931 | this.addConfig();
932 | this.paintShadow();
933 | };
934 |
935 | ShadowPainter.prototype.onChangeDots = function (elem) {
936 | this.Scene.oneSide = Number(elem.value);
937 |
938 | this.addConfig();
939 | this.createInputsSet();
940 | this.paintShadow();
941 | };
942 |
943 | // -----------------------------------------
944 |
945 | ShadowPainter.prototype.createDotsInp = function () {
946 | this.Elems.dotsInp.value = this.Scene.oneSide;
947 |
948 | this.addDataDefautlt(this.Elems.dotsInp, this.Scene.oneSide);
949 | this.addOnChangeEvents(this.classNames.dotsInp, this.onChangeDots);
950 | };
951 |
952 | // -----------------------------------------
953 |
954 | ShadowPainter.prototype.initColors = function() {
955 | const colors = {
956 | className: 'color',
957 | inputType: 'radio',
958 | inputClass: 'color__inp',
959 | inputData: 'data-color="{color}" ',
960 |
961 | labelContent: '',
962 | controlClass: 'colors-controls__item',
963 | transparent: 'rgba(255,255,255,0)',
964 | currentNum: 0,
965 | currentListNum: 0
966 | };
967 |
968 | colors.list = this.Palettes[colors.currentListNum];
969 |
970 | colors.current = colors.list[0];
971 | colors.classCurrent = `${colors.className}--${colors.currentNum}`;
972 |
973 | colors.StyleTempl = `.${colors.className}--{i} {background: {color};}\n`;
974 | colors.controlTempl = '';
975 |
976 | colors.upDown = {
977 | list: {
978 | 'up': '',
979 | 'down': ''
980 | },
981 | replacements: {
982 | '{itemsClass}': colors.controlClass
983 | },
984 | template: ''
985 | };
986 |
987 | return colors;
988 | };
989 |
990 | // -----------------------------------------
991 |
992 | ShadowPainter.prototype.initStep = function() {
993 | const step = {
994 | className: 'step',
995 | inputType: 'radio',
996 | inputClass: 'step__inp',
997 | inputData: '',
998 | labelContent: '{i+1}',
999 | controlClass: 'steps-control',
1000 | clearFramesClass: 'frames-clear',
1001 |
1002 | currentNum: 0,
1003 | customClass: '{customClass}',
1004 | hiddenClass: 'is-hidden',
1005 | disabledClass: 'is-disabled'
1006 | };
1007 | step.plusMinus = {
1008 | list: {
1009 | 'minus': '–',
1010 | 'plus': '+'
1011 | },
1012 | replacements: {
1013 | '{itemsClass}': step.controlClass
1014 | },
1015 | template: '{text}',
1016 | insertBetween: 'this.Frames'
1017 | };
1018 |
1019 | step.clearFrames = {
1020 | list: {
1021 | 'current': 'Clear current frame',
1022 | 'all': 'Clear all frames'
1023 | },
1024 | replacements: {
1025 | '{itemsClass}': step.clearFramesClass
1026 | },
1027 | template: '{text}'
1028 | };
1029 |
1030 | return step;
1031 | };
1032 |
1033 | // Helpers
1034 | // -----------------------------------------
1035 |
1036 | function out(data, is_style, color) {
1037 | var style;
1038 |
1039 | if (is_style) {
1040 | color = color || 'orangered';
1041 | style = 'color: ' + color + '; padding-left: 20px;';
1042 | style = `color: ${color}; padding-left: 20px;`;
1043 | data = `%c${data}`;
1044 | console.log(data, style);
1045 | }
1046 | else {
1047 | console.log(data);
1048 | }
1049 | }
1050 |
1051 | // -----------------------------------------
1052 |
1053 | function addStylesElem(elemClass) {
1054 | var elem = document.createElement('style');
1055 | elem.classList.add(elemClass);
1056 | var head = document.querySelector('head');
1057 | head.appendChild(elem);
1058 | return elem;
1059 | }
1060 |
1061 | // -----------------------------------------
1062 |
1063 | function findKeyFrames(name) {
1064 | var keyFrames;
1065 | var sheets = document.styleSheets;
1066 |
1067 | for (var i = 0; i < sheets.length; i++) {
1068 | try {
1069 | var stylesList = sheets[i].cssRules;
1070 |
1071 | for (var k = 0; k < stylesList.length; k++) {
1072 | if (stylesList[k].name === name) {
1073 | keyFrames = stylesList[k];
1074 | }
1075 | }
1076 | }
1077 | catch {}
1078 |
1079 | }
1080 |
1081 | return keyFrames;
1082 | }
1083 |
1084 | // -----------------------------------------
1085 |
1086 | function checkClassDot(className) {
1087 | if (className.indexOf('.') < 0) {
1088 | className = '.' + className;
1089 | }
1090 | return className;
1091 | }
1092 |
1093 | // -----------------------------------------
1094 |
1095 | function strIsNAN(str) {
1096 | str = str.replace(/-|\./g,'');
1097 | str = str.split(' ').join('');
1098 | return isNaN(str);
1099 | }
1100 |
1101 | // -----------------------------------------
1102 |
1103 | function addUnits(str) {
1104 | str = String(str);
1105 | var arr = str.split(' ');
1106 |
1107 | if (strIsNAN(str)) {
1108 | return str;
1109 | }
1110 |
1111 | if (arr.length > 1 &&
1112 | arr[0].indexOf('px') < 0 &&
1113 | arr[0].indexOf('em') < 0 &&
1114 | arr[0].indexOf('%') < 0) {
1115 | str = arr.join('px ') + 'px';
1116 | return str;
1117 | }
1118 |
1119 | if (str.indexOf('px') < 0 &&
1120 | str.indexOf('em') < 0 &&
1121 | arr[0].indexOf('%') < 0) {
1122 | str += 'px';
1123 | }
1124 |
1125 | return str;
1126 | }
1127 |
1128 | // -----------------------------------------
1129 |
1130 | function getValByKeyCode(elem, key, isShift) {
1131 | var value = Number(elem.value);
1132 | var min = elem.getAttribute('data-min');
1133 | var max = elem.getAttribute('data-max');
1134 |
1135 | var step = isShift ? 10 : 1;
1136 |
1137 | if (key === 38) {
1138 | if (value >= 0 &&
1139 | value < 1 &&
1140 | min < 1) {
1141 |
1142 | step = 0.1;
1143 | }
1144 | value += step;
1145 | }
1146 | else if (key === 40) {
1147 | if (value > 0 &&
1148 | value <= 1 &&
1149 | min < 1) {
1150 |
1151 | step = 0.1;
1152 | }
1153 | value -= step;
1154 | }
1155 |
1156 | if (value < min) {
1157 | value = min;
1158 | }
1159 | else if (max !== null && value > max) {
1160 | value = max;
1161 | }
1162 | else {
1163 | if (value > 0 && value < 1) {
1164 | value = value.toFixed(1);
1165 | }
1166 | else {
1167 | value = value.toFixed();
1168 | }
1169 | }
1170 |
1171 | return value;
1172 | }
1173 |
1174 | // -----------------------------------------
1175 |
1176 | function valueSetDefaultIfNAN(elem) {
1177 | var value = elem.value;
1178 | var defaultValue = elem.getAttribute('data-default');
1179 | if (isNaN(value)) {
1180 | return defaultValue;
1181 | }
1182 |
1183 | return false;
1184 | }
1185 |
1186 | // -----------------------------------------
1187 |
1188 | function minMaxDef(elem) {
1189 | var min = elem.getAttribute('data-min');
1190 | min = min === null ? 0 : Number(min);
1191 |
1192 | var max = elem.getAttribute('data-max');
1193 | max = max === null ? 100 : Number(max);
1194 |
1195 | var value = elem.value;
1196 |
1197 | var out = value > max ? max : value < min ? min : false;
1198 | return out;
1199 | }
1200 |
1201 | // -----------------------------------------
1202 |
1203 | function createTemplate(item) {
1204 | var itemType = item.className;
1205 | var inputType = item.inputType;
1206 | var data_attr = item.inputData;
1207 | var lblContent = item.labelContent;
1208 | var itemCustomClass = item.customClass ? item.customClass : '';
1209 |
1210 | var itemInpClass = itemType + '__inp';
1211 | var itemLblClass = itemType + '__lbl';
1212 |
1213 | var replacements = {
1214 | '{inputType}': inputType,
1215 | '{itemType}': itemType,
1216 | '{itemClass}': itemType,
1217 | '{itemLblClass}': itemLblClass,
1218 | '{itemInpClass}': itemInpClass,
1219 | '{lblContent}': lblContent
1220 | };
1221 |
1222 | var itemInputTempl = ``;//
1223 | var itemLabelTempl = ``;
1224 | var itemTempl = `${itemInputTempl}${itemLabelTempl}`;
1225 |
1226 | var result = fillTemplate(itemTempl, replacements);
1227 |
1228 | return result;
1229 | }
1230 |
1231 | // -----------------------------------------
1232 |
1233 | function fillTemplate(dataStr, replacements) {
1234 | for (var key in replacements) {
1235 | var findStr = key;
1236 | var replaceWithStr = replacements[key];
1237 |
1238 | dataStr = dataStr.split(findStr).join(replaceWithStr);
1239 | }
1240 | return dataStr;
1241 | }
1242 |
1243 | // -----------------------------------------
1244 |
1245 | function objLength(obj) {
1246 | var count = 0;
1247 | for (var key in obj) {
1248 | count++;
1249 | }
1250 | return count;
1251 | }
1252 |
1253 | // Init
1254 | // -----------------------------------------
1255 |
1256 | var painter = new ShadowPainter();
1257 |
1258 | painter.init();
1259 |
1260 |
--------------------------------------------------------------------------------
/src/scss/reset.scss:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h2, h3, h4, h5, h6,
2 | p, a, img, b, i, dl, dt, dd, ol, ul, li,
3 | label, article, aside, footer, header, section {
4 | margin: 0;
5 | padding: 0;
6 | border: 0;
7 | font-size: 100%;
8 | font: inherit;
9 | vertical-align: baseline;
10 | }
11 | body {
12 | line-height: 1;
13 | }
14 | ol, ul {
15 | list-style: none;
16 | }
17 |
--------------------------------------------------------------------------------
/src/scss/styles.scss:
--------------------------------------------------------------------------------
1 | $sideCells: 10;
2 | $dotSize: 30px;
3 | $box-size: $dotSize * $sideCells;
4 | $radius: 0;
5 |
6 | $padding: 20px;
7 |
8 | $hello-height: 150px;
9 |
10 | $color-border: #CCC;
11 | $color-active: orange;
12 | $color-step: lightgray;
13 | $color-step-l: lighten($color-step, 12);
14 | $color-step-d: darken($color-step, 20);
15 |
16 | @mixin clear {
17 | content: '';
18 | display: table;
19 | width: 100%;
20 | clear: both;
21 | }
22 |
23 | @mixin dotted-text($color: #555) {
24 | border-bottom: 1px dotted;
25 | line-height: 1.2;
26 | color: $color;
27 | cursor: pointer;
28 | }
29 |
30 | $time: 1s;
31 |
32 | @import "reset";
33 |
34 | * {
35 | box-sizing: border-box;
36 | }
37 |
38 | HTML,
39 | BODY {
40 | height: 100%;
41 | }
42 |
43 | BODY {
44 | display: flex;
45 | align-items: center;
46 | justify-content: center;
47 | background: #FFF;
48 | font: 14px/1.4 'Trebuchet MS', Verdana, sans-serif;
49 | color: #333;
50 | }
51 |
52 | LABEL {
53 | cursor: pointer;
54 | }
55 |
56 | .l-wrapper {
57 | position: relative;
58 | border: 1px solid $color-border;
59 | white-space: nowrap;
60 |
61 | &:after {
62 | @include clear;
63 | }
64 | }
65 |
66 | .b-boxes {
67 | position: relative;
68 | text-align: center;
69 | border: 1px solid $color-border;
70 | border-width: 1px 0;
71 | }
72 | .l-zero-gravity {
73 | position: absolute;
74 | width: 100%;
75 | top: 0;
76 | bottom: 0;
77 | right: 0;
78 | left: 0;
79 | margin: auto;
80 | }
81 | .b-box {
82 | position: relative;
83 | display: inline-block;
84 | border: 1px solid $color-border;
85 | &:nth-of-type(1){
86 | margin-right: $padding;
87 | }
88 | }
89 | .b-panel {
90 | padding: $padding/2;
91 | color: #888;
92 | &:before,
93 | &:after {
94 | @include clear;
95 | }
96 | }
97 |
98 |
99 | .b-panel--top {
100 | }
101 |
102 | .b-panel--bottom {
103 | }
104 |
105 |
106 | .b-title {
107 | display: inline-block;
108 | padding-right: $padding/2;
109 | line-height: $dotSize;
110 | }
111 |
112 | .b-steps .b-title {
113 | float: none;
114 | display: inline-block;
115 | margin: 0 auto;
116 | padding: 0;
117 | }
118 |
119 | /* Paint Box
120 | ----------------------------- */
121 | .b-box--paint {
122 | overflow: hidden;
123 | border-width: 0 1px 1px 0;
124 | background-image:
125 | linear-gradient( to right,
126 | $color-border 1px,
127 | transparent 1px
128 | ),
129 | linear-gradient( to bottom,
130 | $color-border 1px,
131 | transparent 1px
132 | );
133 | background-position: 0 0;
134 | }
135 |
136 | /* Labels
137 | ----------------------------- */
138 | .cell {
139 | display: block;
140 | float: left;
141 | }
142 | .cell__inp {
143 | position: absolute;
144 | display: none;
145 | }
146 | .cell__lbl {
147 | display: block;
148 | border-radius: $radius;
149 | /*box-shadow: 0 0 2px #999 inset;*/
150 | }
151 |
152 | :checked + .cell__lbl {
153 | position: relative;
154 | }
155 | .is-colored {
156 | background: $color-active;
157 | }
158 |
159 | /* Result Box
160 | ----------------------------- */
161 | .b-box--result {
162 | overflow: hidden;
163 | }
164 |
165 | /* Dotts
166 | ----------------------------- */
167 |
168 | .dot {
169 | display: block;
170 | position: absolute;
171 | border-radius: $radius;
172 | }
173 | .dot--previous {
174 | opacity: .2;
175 | }
176 |
177 | .is-running{
178 | }
179 |
180 | @keyframes shadows {}
181 |
182 | /* Palette
183 | ----------------------------- */
184 | .b-palette {
185 | display: inline-block;
186 | }
187 | .items--colors {
188 | display: inline-block;
189 | vertical-align: middle;
190 | }
191 | .color {
192 | display: inline-block;
193 | width: $dotSize;
194 | height: $dotSize;
195 | }
196 | .color__inp {
197 | display: none;
198 | }
199 |
200 | .color__lbl {
201 | display: block;
202 | height: $dotSize;
203 | }
204 | :checked + .color__lbl {
205 | position: relative;
206 | z-index: 1;
207 | box-shadow: 0 0 0 3px rgba(0, 0, 0, .3);
208 | }
209 |
210 | /* Color Controls
211 | ----------------------------- */
212 | .items--colors-controls {
213 | display: inline-block;
214 | position: relative;
215 | height: $dotSize;
216 | margin-left: 5px;
217 | vertical-align: middle;
218 | }
219 | .colors-controls__item {
220 | position: absolute;
221 | border: 10px solid transparent;
222 | border-color: $color-step-d transparent;
223 | border-width: 10px 4px;
224 | cursor: pointer;
225 | &:hover {
226 | border-color: darken($color-step-d, 10) transparent;
227 | }
228 | &:active {
229 | border-color: darken($color-step-d, 30) transparent;
230 | }
231 | }
232 | .colors-controls__item--up {
233 | top: 0;
234 | border-top: 0;
235 | &:active {
236 | top: 2px;
237 | }
238 | }
239 | .colors-controls__item--down {
240 | bottom: 0;
241 | border-bottom: 0;
242 | &:active {
243 | bottom: -2px;
244 | }
245 | }
246 | /* Panel
247 | ----------------------------- */
248 | .b-panel {
249 | position: relative;
250 | }
251 | .b-panel__item {
252 | float: left;
253 | margin-left: $padding*1.6;
254 | &:first-child {
255 | margin-left: 0;
256 | }
257 | }
258 | .text--value {
259 | width: 3.5em;
260 | height: $dotSize;
261 | line-height: $dotSize;
262 | pading: 0;
263 | border: 1px solid $color-border;
264 | border-radius: 5px;
265 | text-align: center;
266 | }
267 |
268 | /* Steps
269 | ----------------------------- */
270 | .b-steps {
271 | text-align: center;
272 | -webkit-user-select: none;
273 | -moz-user-select: none;
274 | -ms-user-select: none;
275 | user-select: none;
276 | }
277 | .steps-control {
278 | display: inline-block;
279 | position: relative;
280 | width: $dotSize*.8;
281 | height: $dotSize*.8;
282 | line-height: $dotSize*.8;
283 | margin: 0 6px;
284 | top: 0;
285 | background: $color-step;
286 | font-weight: bold;
287 | color: #444;
288 | cursor: pointer;
289 | -webkit-transition: all .1s;
290 | transition: all .2s;
291 | }
292 | .steps-control:hover {
293 | top: -1px;
294 | background: $color-step-l;
295 | color: #555;
296 | }
297 | .steps-control:active {
298 | top: 1px;
299 | background: $color-step-d;
300 | color: #FFF;
301 | }
302 |
303 | .is-disabled,
304 | .is-disabled:hover {
305 | top: 0;
306 | background: $color-step-l;
307 | color: #AAA;
308 | cursor: default;
309 | }
310 |
311 | .items--steps {
312 | display: block;
313 | margin-top: 10px;
314 | }
315 | .step {
316 | display: inline-block;
317 | width: $dotSize;
318 | height: $dotSize;
319 | margin-right: 1px;
320 | line-height: $dotSize;
321 | background: $color-step-l;
322 | text-align: center;
323 | }
324 | .step__inp {
325 | position: absolute;
326 | display: none;
327 | }
328 | .step__lbl {
329 | display: block;
330 | height: $dotSize;
331 | }
332 | .is--filled + .step__lbl {
333 | background: $color-step;
334 | }
335 |
336 | :checked + .step__lbl {
337 | position: relative;
338 | z-index: 1;
339 | background: $color-step-d;
340 | box-shadow: 0 0 0 3px rgba(0, 0, 0, .3);
341 | color: #FFF;
342 | }
343 |
344 | .is-hidden {
345 | display: none;
346 | }
347 |
348 | .frames-clear {
349 | position: absolute;
350 | top: $padding/2;
351 | &:hover {
352 | padding-top: 1px;
353 | }
354 | }
355 |
356 | .frames-clear--current {
357 | left: $padding/2;
358 | @include dotted-text;
359 | }
360 | .frames-clear--all {
361 | right: $padding/2;
362 | @include dotted-text(orangered);
363 | }
364 |
365 | .is--sleepy {
366 | color: #777
367 | }
368 | /* Codes
369 | ----------------------------- */
370 | .b-codes {
371 | /*display: none;*/
372 |
373 | position: absolute;
374 | z-index: 10;
375 | top: 0;
376 | right: 0;
377 | left: 0;
378 | background: rgba(240, 240, 240, .9);
379 | box-shadow: 0 0 20px rgba(0, 0, 0, .3);
380 |
381 | }
382 | .is-open {
383 | right: -.5em;
384 | left: -.5em;
385 | box-shadow: 0 0 20px rgba(0, 0, 0, .3),
386 | 0 0 0 1000px rgba(255, 255, 255, .8);
387 | }
388 |
389 | .b-codes__toggle {
390 | position: absolute;
391 | top: -$padding*1.2;
392 | right: $padding/2;
393 | @include dotted-text;
394 | &:hover {
395 | padding-top: 1px;
396 | }
397 | }
398 | .b-codes__wrapper {
399 | display: none;
400 | padding: $padding;
401 | border: 1px solid #BBB;
402 | .is-open & {
403 | display: block;
404 | }
405 | }
406 |
407 | .b-codes--title {
408 | margin-bottom: $padding/3;
409 | color: #777;
410 | }
411 | .b-codes__textarea {
412 | display: block;
413 | width: 100%;
414 | height: $dotSize*4;
415 | border: 1px solid $color-border;
416 | }
417 | .textarea--css {
418 | margin-bottom: $padding;
419 | }
420 |
421 |
422 | .hello {
423 | display: none;
424 | position: absolute;
425 | z-index: 10;
426 | height: $hello-height;
427 | width: 100%;
428 | top: -1em;
429 | bottom: -1em;
430 | margin: auto;
431 | background: rgba(0,0,0,.3);
432 | text-shadow: 0 0 3px rgba(0,0,0,.5);
433 | text-align: center;
434 | color: #FFF;
435 | H2 {
436 | margin-bottom: 10px;
437 | font-size: 4em;
438 | }
439 | SPAN {
440 | font-size: 2em;
441 | }
442 | &:before {
443 | content: "";
444 | display: inline-block;
445 | height: $hello-height;
446 | vertical-align: middle;
447 | }
448 | }
449 | .hello__text {
450 | display: inline-block;
451 | vertical-align: middle;
452 | }
453 | @media (max-width: 760px){
454 | .hello {
455 | display: block;
456 | }
457 | }
458 |
--------------------------------------------------------------------------------