-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
116 lines (95 loc) · 3.79 KB
/
script.js
File metadata and controls
116 lines (95 loc) · 3.79 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
115
116
document.addEventListener('DOMContentLoaded', () => {
// Grid Trail Effect
const gridContainer = document.getElementById('gridContainer');
const dotSize = 50; // Distance between dots in pixels
function createGrid() {
gridContainer.innerHTML = '';
const gridBackground = document.createElement('div');
gridBackground.className = 'grid-background';
const cols = Math.ceil(window.innerWidth / dotSize);
const rows = Math.ceil(window.innerHeight / dotSize);
gridBackground.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
gridBackground.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
const totalDots = cols * rows;
const dots = [];
for (let i = 0; i < totalDots; i++) {
const dot = document.createElement('div');
dot.className = 'grid-dot';
gridBackground.appendChild(dot);
dots.push(dot);
}
gridContainer.appendChild(gridBackground);
return dots;
}
let dots = createGrid();
window.addEventListener('resize', () => {
dots = createGrid();
});
document.addEventListener('mousemove', (e) => {
const mouseX = e.clientX;
const mouseY = e.clientY;
dots.forEach(dot => {
const rect = dot.getBoundingClientRect();
const dotX = rect.left + rect.width / 2;
const dotY = rect.top + rect.height / 2;
const dist = Math.hypot(mouseX - dotX, mouseY - dotY);
if (dist < 100) {
dot.classList.add('active');
// Calculate scale based on distance
const scale = 1 + (1.5 * (1 - dist / 100));
dot.style.transform = `scale(${scale})`;
} else {
dot.classList.remove('active');
dot.style.transform = 'scale(1)';
}
});
});
// Theme Logic
const themeToggle = document.getElementById('themeToggle');
const htmlElement = document.documentElement;
const themeIcon = themeToggle.querySelector('i');
const savedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const applyTheme = (theme) => {
htmlElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
if (theme === 'dark') {
themeIcon.className = 'fa-regular fa-sun';
} else {
themeIcon.className = 'fa-regular fa-moon';
}
};
applyTheme(savedTheme || (prefersDark ? 'dark' : 'light'));
themeToggle.addEventListener('click', () => {
const currentTheme = htmlElement.getAttribute('data-theme');
const nextTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(nextTheme);
});
// Tool Card Hover Micro-interactions (Optional)
const cards = document.querySelectorAll('.tool-card');
cards.forEach(card => {
card.addEventListener('mouseenter', () => {
// Potential for more complex animations if needed
});
});
// Reveal animations on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
observer.unobserve(entry.target);
}
});
}, observerOptions);
cards.forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `all 0.5s cubic-bezier(0.4, 0, 0.2, 1) ${index * 0.1}s`;
observer.observe(card);
});
});