-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjavascript.js
More file actions
114 lines (94 loc) · 3.53 KB
/
javascript.js
File metadata and controls
114 lines (94 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"use strict"
let inkMode = 'black';
const container = document.querySelector('.container');
const gridSizeEl = document.querySelector('#grid-size');
const gridSizeForm = document.querySelector('#grid-size-form');
const gridlinesToggle = document.querySelector('#gridlines-toggle');
const rainbowToggle = document.querySelector('#rainbow-toggle');
generatePixels(Number(gridSizeEl.value));
addMouseHandlers();
gridSizeForm.addEventListener('submit', (e) => {
e.preventDefault(); // prevents automatic page refresh on form submission
const gridSize = Number(gridSizeEl.value);
redrawGrid(gridSize);
});
gridlinesToggle.addEventListener('change', (e) => {
container.classList.toggle('gridlines');
});
rainbowToggle.addEventListener('change', (e) => {
if (rainbowToggle.checked) {
inkMode = 'rainbow';
} else {
inkMode = 'black';
}
})
container.addEventListener("touchmove", touchHandling, {passive: false});
let lastTouched;
function touchHandling(e) {
if (e.touches.length !== 1) return;
e.preventDefault(); // Prevent single point touchmove from triggering scrolling
const touch = e.touches[0];
const touchedEl = document.elementFromPoint(touch.clientX, touch.clientY);
if (touchedEl?.classList.contains('pixel') && lastTouched !== touchedEl) {
colorPixel(touchedEl);
lastTouched = touchedEl;
}
}
function addMouseHandlers() {
const pixels = document.querySelectorAll('.pixel');
pixels.forEach((pixel) => {
pixel.addEventListener('mouseenter', () => {
colorPixel(pixel);
});
});
}
function randomRgbInt() {
return Math.floor(Math.random() * 256); // Generate random number from 0-255
}
// Returns array of RGB values
function rgbArray(inkMode) {
switch (inkMode) {
case 'black':
return [0, 0, 0];
case 'rainbow':
return [randomRgbInt(), randomRgbInt(), randomRgbInt()];
}
}
// Constructs rbga string from rgb array and alpha
// Example: rgbaString([255, 255, 255], 0.5) -> 'rgba(255, 255, 255, 0.5)'
function rgbaString(rgb, alpha) {
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${alpha})`;
}
// Returns true if opaque (i.e. no alpha channel or alpha channel is 1)
// Example inputs: 'rgb(0, 0, 0)', 'rgba(0, 0, 0, 1)', 'rgba(0,0,0,1)' (no spaces), 'rgba(0,0,0,0.1)'
function isOpaque(rgbString) {
return (!rgbString.includes('rgba') || (rgbString.includes('rgba') && parseFloat(rgbString.split(',')[3]) === 1));
}
function generatePixels(gridDimension) {
for (let i = 0; i < gridDimension ** 2; i++) {
const pixel = document.createElement('div');
pixel.classList.add('pixel');
pixel.style.width = ((1/gridDimension) * 100) + '%';
container.append(pixel);
}
}
// Add pixel color and increase opacity by 10% every time the mouse passes through
function colorPixel(pixel) {
const currentPixelColor = pixel.style.backgroundColor;
if (!currentPixelColor) {
pixel.style.backgroundColor = rgbaString(rgbArray(inkMode), 0.1);
} else if (!isOpaque(currentPixelColor)) { // opacity is >= 0.1 and <= 0.9;
const opacity = Number(currentPixelColor.slice(-4, -1)); // gets opacity: 'rgba(0, 0, 0, 0.2)' --> 0.2
pixel.style.backgroundColor = rgbaString(rgbArray(inkMode), opacity + 0.1);
} else {
pixel.style.backgroundColor = rgbaString(rgbArray(inkMode), 1);
}
}
function clearGrid() {
container.innerHTML = '';
}
function redrawGrid(gridSize) {
clearGrid();
generatePixels(gridSize);
addMouseHandlers();
}