Skip to content

Commit a7cb067

Browse files
committed
i
i
1 parent 5b713f9 commit a7cb067

7 files changed

Lines changed: 396 additions & 359 deletions

File tree

dist/bundle-b671e.js

Lines changed: 0 additions & 2 deletions
This file was deleted.

dist/bundle-f8d3e.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/js/background.js

Lines changed: 78 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,72 @@
1-
// if (!isMobile || !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
21
const shiftLayer1 = document.getElementById("shift-layer1");
32
const shiftLayer2 = document.getElementById("shift-layer2");
43
const bg = document.getElementById('bg');
5-
let shiftLayer1State = createLayerState(shiftLayer1);
6-
let shiftLayer2State = createLayerState(shiftLayer2);
7-
let bgState = createBgLayerState(bg);
4+
5+
const allShiftLayers = Array.from(document.querySelectorAll('[id^="shift-layer"]'));
6+
const totalShiftLayers = allShiftLayers.length;
7+
88
function getShiftLayerInfo(element) {
9-
const allLayers = document.querySelectorAll('[id^="shift-layer"]');
10-
const totalLayers = allLayers.length;
119
const match = element.id.match(/shift-layer(\d+)/);
1210
const currentLayer = match ? parseInt(match[1]) : null;
13-
return { currentLayer, totalLayers };
11+
return { currentLayer, totalLayers: totalShiftLayers };
1412
}
13+
14+
let shiftLayer1State = createLayerState(shiftLayer1);
15+
let shiftLayer2State = createLayerState(shiftLayer2);
16+
let bgState = createBgLayerState(bg);
17+
1518
function randomlyModifyValue(value, minFactor = 0.85, maxFactor = 1.15) {
1619
if (Math.random() < 0.333) {
1720
const factor = Math.random() * (maxFactor - minFactor) + minFactor;
1821
return Math.round(value * factor);
1922
}
2023
return Math.round(value);
2124
}
25+
2226
function getRandomInRange(min, max, modifier = 1, element) {
2327
if (!element.id.startsWith('shift-layer')) {
2428
return (Math.random() * (max - min) + min) * modifier;
2529
}
26-
const { currentLayer, totalLayers } = getShiftLayerInfo(element);
27-
for (let i = 1; i <= totalLayers; i++) {
28-
if (currentLayer === i) {
29-
return randomlyModifyValue(Math.random() * (max - min) + min) * modifier;
30-
}
30+
const { currentLayer } = getShiftLayerInfo(element);
31+
if (currentLayer != null) {
32+
return randomlyModifyValue(Math.random() * (max - min) + min) * modifier;
3133
}
34+
return (Math.random() * (max - min) + min) * modifier;
35+
}
36+
37+
function roundTo(value, decimals) {
38+
const factor = 10 ** decimals;
39+
return Math.round(value * factor) / factor;
3240
}
41+
3342
function getRandomTransitionDuration(element) {
34-
const randomValue = getRandomInRange(7000, 21000, 1, element);
35-
return Math.round(randomValue);
43+
return Math.round(getRandomInRange(7000, 21000, 1, element));
3644
}
45+
3746
function getRandomHueShift(element) {
38-
const randomValue = getRandomInRange(-180, 180, 1, element);
39-
return Math.round(randomValue * 10) / 10;
47+
return roundTo(getRandomInRange(-180, 180, 1, element), 1);
4048
}
49+
4150
function getRandomFilterValue(element) {
42-
const randomValue = getRandomInRange(87, 185, 1, element);
43-
return Math.round(randomValue * 10) / 10;
51+
return roundTo(getRandomInRange(87, 185, 1, element), 1);
4452
}
53+
4554
function getRandomOpacityValue(element) {
46-
const randomValue = getRandomInRange(65, 95, 1, element);
47-
return Math.round(randomValue * 10) / 10;
55+
return roundTo(getRandomInRange(65, 95, 1, element), 1);
4856
}
57+
4958
function getRandomOpacityValue2(element) {
50-
const randomValue = getRandomInRange(.29, .37, 1, element);
51-
return Math.round(randomValue * 1000) / 1000;
59+
return roundTo(getRandomInRange(0.29, 0.37, 1, element), 3);
5260
}
61+
5362
function getRandomGradientSteps(element) {
5463
const { currentLayer } = getShiftLayerInfo(element);
55-
return currentLayer === 1 ? 7 * Math.ceil(Math.random() * 7) : randomlyModifyValue(Math.ceil(Math.random() * 12) + 2);
64+
if (currentLayer === 1) {
65+
return 7 * Math.ceil(Math.random() * 7);
66+
}
67+
return randomlyModifyValue(Math.ceil(Math.random() * 12) + 2);
5668
}
69+
5770
function createLayerState(element) {
5871
const { currentLayer } = getShiftLayerInfo(element);
5972
return {
@@ -74,13 +87,9 @@ function createLayerState(element) {
7487
targetHueShift: getRandomHueShift(element),
7588
};
7689
}
90+
7791
function createBgLayerState(element) {
78-
let initialOpacity;
79-
if (element.id === 'bg') {
80-
initialOpacity = 0.33;
81-
} else {
82-
initialOpacity = 1;
83-
}
92+
const initialOpacity = element.id === 'bg' ? 0.33 : 1;
8493
return {
8594
transitionCurrentTime: 0,
8695
transitionProgress: 0,
@@ -89,45 +98,60 @@ function createBgLayerState(element) {
8998
targetOpacity: getRandomOpacityValue2(element),
9099
};
91100
}
101+
92102
function setGradient(element, state) {
93103
const { currentLayer } = getShiftLayerInfo(element);
94-
function getAdjustedHue(currentGradientStep, gradientAngle) {
95-
return (currentGradientStep * gradientAngle);
96-
}
97-
const width = element.offsetWidth || element.clientWidth;
104+
const width = element.offsetWidth || element.clientWidth;
98105
const height = element.offsetHeight || element.clientHeight;
99-
const diagonal = Math.sqrt(width * width + height * height);
106+
const diagonal = Math.sqrt(width ** 2 + height ** 2);
100107
const percentage = (diagonal / (Math.max(width, height) * Math.sqrt(2))) * 100;
108+
101109
let gradients = [];
102110
const gradientSteps = state.currentGradientSteps;
103111
const gradientAngle = 360 / gradientSteps;
112+
104113
for (let i = 0; i < gradientSteps; i++) {
105114
const angle = i * gradientAngle;
106115
const x = 50 + 50 * Math.cos(angle * Math.PI / 180);
107116
const y = 50 + 50 * Math.sin(angle * Math.PI / 180);
108-
const currentGradientStep = i + state.currentGradientSteps;
109-
gradients.push(`radial-gradient(ellipse farthest-corner at ${Math.round(x * 10) / 10}% ${Math.round(y * 10) / 10}%, hsl(${getAdjustedHue(currentGradientStep, gradientAngle)}, 100%, 50%), transparent ${Math.round(percentage * 10) / 10}%)`);
117+
const currentGradientStep = i + gradientSteps;
118+
gradients.push(
119+
`radial-gradient(ellipse farthest-corner at ${roundTo(x,1)}% ${roundTo(y,1)}%, hsl(${currentGradientStep * gradientAngle}, 100%, 50%), transparent ${roundTo(percentage,1)}%)`
120+
);
110121
}
122+
111123
element.style.backgroundImage = gradients.join(', ');
112-
element.style.filter = `opacity(${state.currentOpacity}%) contrast(${state.currentContrast}%) brightness(${state.currentBrightness}%) saturate(${state.currentSaturation}%) hue-rotate(${state.currentHueShift}deg)`;
124+
element.style.filter = `
125+
opacity(${state.currentOpacity}%)
126+
contrast(${state.currentContrast}%)
127+
brightness(${state.currentBrightness}%)
128+
saturate(${state.currentSaturation}%)
129+
hue-rotate(${state.currentHueShift}deg)
130+
`.trim();
113131
}
132+
114133
function updateLayerState(state, element, deltaTime) {
115134
state.transitionCurrentTime += deltaTime;
116-
state.transitionProgress += (deltaTime / state.transitionDuration);
117-
if (state.transitionProgress > 1) state.transitionProgress = 1;
135+
state.transitionProgress = Math.min(1, state.transitionProgress + deltaTime / state.transitionDuration);
136+
118137
const t = () => metaRecursiveEaseNoise(state.transitionProgress);
119138
const { currentLayer } = getShiftLayerInfo(element);
139+
140+
const randomFactor = (max) => Math.random() * max;
141+
120142
if (currentLayer === 1) {
121-
state.currentGradientSteps += Math.round((state.targetGradientSteps - state.currentGradientSteps) * (t() * 0.00005) * Math.random() * 10) / 10;
122-
state.currentHueShift += Math.round((state.targetHueShift - state.currentHueShift) * (t() * 0.05) * Math.random() * 10) / 10;
143+
state.currentGradientSteps += Math.round((state.targetGradientSteps - state.currentGradientSteps) * t() * 0.00005 * randomFactor(10)) / 10;
144+
state.currentHueShift += Math.round((state.targetHueShift - state.currentHueShift) * t() * 0.05 * randomFactor(10)) / 10;
123145
} else {
124-
state.currentGradientSteps += Math.round((state.targetGradientSteps - state.currentGradientSteps) * (t() * 0.05) * Math.random() * 10) / 10;
125-
state.currentHueShift += Math.round((state.targetHueShift - state.currentHueShift) * (t() * 0.01) * Math.random() * 10) / 10;
146+
state.currentGradientSteps += Math.round((state.targetGradientSteps - state.currentGradientSteps) * t() * 0.05 * randomFactor(10)) / 10;
147+
state.currentHueShift += Math.round((state.targetHueShift - state.currentHueShift) * t() * 0.01 * randomFactor(10)) / 10;
126148
}
127-
state.currentContrast += Math.round((state.targetContrast - state.currentContrast) * (t() * Math.random()) * 10) / 10;
128-
state.currentBrightness += Math.round((state.targetBrightness - state.currentBrightness) * (t() * Math.random()) * 10) / 10;
129-
state.currentSaturation += Math.round((state.targetSaturation - state.currentSaturation) * (t() * Math.random()) * 10) / 10;
130-
state.currentOpacity += Math.round((state.targetOpacity - state.currentOpacity) * (t() * Math.random()) * 10) / 10;
149+
150+
state.currentContrast += Math.round((state.targetContrast - state.currentContrast) * t() * randomFactor(1) * 10) / 10;
151+
state.currentBrightness += Math.round((state.targetBrightness - state.currentBrightness) * t() * randomFactor(1) * 10) / 10;
152+
state.currentSaturation += Math.round((state.targetSaturation - state.currentSaturation) * t() * randomFactor(1) * 10) / 10;
153+
state.currentOpacity += Math.round((state.targetOpacity - state.currentOpacity) * t() * randomFactor(1) * 10) / 10;
154+
131155
if (state.transitionCurrentTime >= state.transitionDuration) {
132156
state.transitionCurrentTime = 0;
133157
state.transitionProgress = 0;
@@ -140,19 +164,23 @@ function updateLayerState(state, element, deltaTime) {
140164
state.targetOpacity = getRandomOpacityValue(element);
141165
}
142166
}
167+
143168
function updateBgLayerState(state, element, deltaTime) {
144169
state.transitionCurrentTime += deltaTime;
145-
state.transitionProgress += (deltaTime / state.transitionDuration) * Math.random();
146-
if (state.transitionProgress > 1) state.transitionProgress = 1;
170+
state.transitionProgress = Math.min(1, state.transitionProgress + (deltaTime / state.transitionDuration) * Math.random());
171+
147172
const t = () => metaRecursiveEaseNoise(state.transitionProgress);
148-
state.currentOpacity += Math.round((state.targetOpacity - state.currentOpacity) * t() * (Math.random() * 1) * 1000) / 1000;
173+
174+
state.currentOpacity += Math.round((state.targetOpacity - state.currentOpacity) * t() * Math.random() * 1000) / 1000;
175+
149176
if (state.transitionCurrentTime >= state.transitionDuration) {
150177
state.transitionCurrentTime = 0;
151178
state.transitionProgress = 0;
152179
state.transitionDuration = getRandomTransitionDuration(element);
153180
state.targetOpacity = element.id === 'bg' ? getRandomOpacityValue2(element) : getRandomOpacityValue(element);
154181
}
155182
}
183+
156184
function updateColors(updateTime) {
157185
if (!isWindowActive) {
158186
requestAnimationFrame(updateColors);
@@ -169,4 +197,3 @@ function updateColors(updateTime) {
169197
requestAnimationFrame(updateColors);
170198
}
171199
requestAnimationFrame(updateColors);
172-
// }

src/js/color-change.js

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,115 @@
1-
// if (!isMobile || !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
21
const hoverShift = document.querySelectorAll('button, a, .article-nav-bottom, footer');
32
const alwaysShift = document.querySelectorAll('header, #site-title, #toolbar, nav .col a, .article-header, .article-title, .section-nav, footer');
4-
function getRandomDegree() {return Math.random() < 0.5 ? Math.floor(Math.random() * -270) - 45 : Math.floor(Math.random() * 270) + 46;}
5-
function getRandomInterval() {return Math.floor(Math.random() * 14000) + 7000;}
3+
4+
function getRandomDegree() {
5+
// More uniform distribution and efficient rounding
6+
return Math.random() < 0.5
7+
? -45 - Math.floor(Math.random() * 270)
8+
: 46 + Math.floor(Math.random() * 224);
9+
}
10+
11+
function getRandomInterval() {
12+
return 7000 + Math.floor(Math.random() * 14000);
13+
}
14+
615
function isElementInViewport(el) {
716
const rect = el.getBoundingClientRect();
8-
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
9-
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
10-
const verticalEdgeThreshold = viewportHeight * 0.8;
17+
const vh = window.innerHeight || document.documentElement.clientHeight;
18+
const vw = window.innerWidth || document.documentElement.clientWidth;
19+
const edgeThreshold = vh * 0.8;
1120
return (
12-
rect.top >= -verticalEdgeThreshold &&
21+
rect.top >= -edgeThreshold &&
1322
rect.left >= 0 &&
14-
rect.bottom <= viewportHeight + verticalEdgeThreshold &&
15-
rect.right <= viewportWidth
23+
rect.bottom <= vh + edgeThreshold &&
24+
rect.right <= vw
1625
);
1726
}
27+
1828
function startShift(element, interval, isHover = false) {
1929
let currentDegree = getRandomDegree();
2030
let targetDegree = currentDegree;
21-
let currentSaturation = 100;
22-
let targetSaturation = 100;
23-
let currentContrast = 100;
24-
let targetContrast = 100;
25-
let currentBrightness = 100;
26-
let targetBrightness = 100;
31+
let currentSaturation = 100, targetSaturation = 100;
32+
let currentContrast = 100, targetContrast = 100;
33+
let currentBrightness = 100, targetBrightness = 100;
2734
let progress = 0;
2835
let lastTime = performance.now();
2936
let isRunning = true;
37+
3038
function updateFilter() {
31-
if (!isRunning) return;
32-
element.style.filter = `
39+
const filterValue = `
3340
hue-rotate(${currentDegree}deg)
3441
saturate(${currentSaturation}%)
3542
contrast(${currentContrast}%)
3643
brightness(${currentBrightness}%)
3744
${isHover ? 'drop-shadow(0 0 1em rgba(255, 255, 255, 0.5))' : ''}
38-
`;
45+
`.trim();
46+
element.style.filter = filterValue;
3947
}
48+
4049
function animate(time) {
4150
if (!isRunning) return;
4251
if (isWindowActive && isElementInViewport(element)) {
4352
const deltaTime = time - lastTime;
4453
lastTime = time;
45-
progress += (deltaTime / interval);
54+
progress += deltaTime / interval;
55+
4656
if (progress >= 1) {
4757
targetDegree = getRandomDegree();
48-
targetSaturation = Math.random() * (125 - 90) + 90;
49-
targetContrast = Math.random() * (isHover ? 170 - 80 : 120 - 80) + 80;
50-
targetBrightness = Math.random() * (isHover ? 135 - 85 : 110 - 90) + (isHover ? 85 : 90);
58+
targetSaturation = Math.random() * 35 + 90; // 90-125
59+
targetContrast = Math.random() * (isHover ? 90 : 40) + 80;
60+
targetBrightness = Math.random() * (isHover ? 50 : 20) + (isHover ? 85 : 90);
5161
progress = 0;
5262
}
63+
5364
const t = () => metaRecursiveEaseNoise(progress);
54-
currentDegree += Math.round((targetDegree - currentDegree) * t() * (Math.random() * .25)) / 10;
55-
currentSaturation += Math.round((targetSaturation - currentSaturation) * t() * (Math.random())) / 10;
56-
currentContrast += Math.round((targetContrast - currentContrast) * t() * (Math.random())) / 10;
57-
currentBrightness += Math.round((targetBrightness - currentBrightness) * t() * (Math.random())) / 10;
65+
66+
currentDegree += Math.round((targetDegree - currentDegree) * t() * Math.random() * 0.07);
67+
currentSaturation += Math.round((targetSaturation - currentSaturation) * t() * Math.random());
68+
currentContrast += Math.round((targetContrast - currentContrast) * t() * Math.random());
69+
currentBrightness += Math.round((targetBrightness - currentBrightness) * t() * Math.random());
70+
5871
updateFilter();
5972
}
60-
if (isRunning) {
61-
requestAnimationFrame(animate);
62-
}
73+
74+
if (isRunning) requestAnimationFrame(animate);
6375
}
76+
6477
requestAnimationFrame(animate);
78+
6579
return () => {
6680
isRunning = false;
6781
element.style.filter = 'none';
6882
};
6983
}
84+
7085
function handleDisengage(element, stopAnimationFunction) {
7186
if (stopAnimationFunction) {
7287
stopAnimationFunction();
7388
}
7489
element.style.filter = 'none';
7590
}
76-
alwaysShift.forEach((element) => {
77-
element.animateFunction = throttle(() => {
78-
return startShift(element, getRandomInterval());
79-
}, 30)();
91+
92+
// Initialize alwaysShift elements with throttled animations
93+
alwaysShift.forEach(element => {
94+
element.animateFunction = throttle(() => startShift(element, getRandomInterval()), 30)();
8095
});
96+
97+
// Initialize hoverShift elements with event handlers and throttle/debounce control
8198
hoverShift.forEach(element => {
82-
let stopAnimationFunction;
83-
let disengageTimeout;
84-
element.addEventListener('mouseover', throttle(() => {
99+
let stopAnimationFunction = null;
100+
let disengageTimeout = null;
101+
102+
const startAnim = throttle(() => {
85103
if (stopAnimationFunction) stopAnimationFunction();
86104
stopAnimationFunction = startShift(element, getRandomInterval(), true);
87-
}, 30));
88-
element.addEventListener('click', () => {
89-
if (stopAnimationFunction) stopAnimationFunction();
90-
stopAnimationFunction = startShift(element, getRandomInterval(), true);
91-
});
105+
}, 30);
106+
107+
element.addEventListener('mouseover', startAnim);
108+
element.addEventListener('click', startAnim);
92109
element.addEventListener('touchstart', () => {
93110
if (stopAnimationFunction) stopAnimationFunction();
94111
stopAnimationFunction = startShift(element, getRandomInterval(), true);
95112
disengageTimeout = setTimeout(() => handleDisengage(element, stopAnimationFunction), 888);
96113
});
97-
element.addEventListener('mouseout', debounce(() => {
98-
handleDisengage(element, stopAnimationFunction);
99-
}, 30));
114+
element.addEventListener('mouseout', debounce(() => handleDisengage(element, stopAnimationFunction), 30));
100115
});
101-
// }

0 commit comments

Comments
 (0)