-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
149 lines (127 loc) · 4.58 KB
/
script.js
File metadata and controls
149 lines (127 loc) · 4.58 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
document.addEventListener("DOMContentLoaded", () => {
// PAGE LOAD
document.body.classList.add("loaded");
window.addEventListener('beforeunload', () => document.body.classList.remove('loaded'));
// FOOTER YEAR
document.getElementById('year').textContent = new Date().getFullYear();
// CUSTOM CURSOR (hover-capable devices only)
const supportsHover = window.matchMedia('(hover: hover) and (pointer: fine)').matches;
const cursorDot = document.querySelector('.cursor-dot');
const cursorRing = document.querySelector('.cursor-ring');
if (supportsHover && cursorDot && cursorRing) {
let mouseX = 0, mouseY = 0;
let ringX = 0, ringY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
cursorDot.style.left = mouseX + 'px';
cursorDot.style.top = mouseY + 'px';
});
(function animateCursor() {
ringX += (mouseX - ringX) * 0.11;
ringY += (mouseY - ringY) * 0.11;
cursorRing.style.left = ringX + 'px';
cursorRing.style.top = ringY + 'px';
requestAnimationFrame(animateCursor);
})();
// Expand ring on interactive elements
document.querySelectorAll('a, button, .skill-tag').forEach(el => {
el.addEventListener('mouseenter', () => {
cursorRing.style.width = '52px';
cursorRing.style.height = '52px';
cursorRing.style.opacity = '0.75';
});
el.addEventListener('mouseleave', () => {
cursorRing.style.width = '34px';
cursorRing.style.height = '34px';
cursorRing.style.opacity = '0.45';
});
});
document.addEventListener('mouseleave', () => {
cursorDot.style.opacity = '0';
cursorRing.style.opacity = '0';
});
document.addEventListener('mouseenter', () => {
cursorDot.style.opacity = '1';
cursorRing.style.opacity = '0.45';
});
}
// TYPEWRITER EFFECT
const typeTarget = document.querySelector('.typewriter');
if (typeTarget) {
const roles = [
"BTech CSE Student @ KIIT",
"C++ & Java Developer",
"AI/ML Explorer",
"Web Developer",
"Building real-world tools",
"Debugging systems",
"Learning by shipping"
];
let roleIndex = 0, charIndex = 0, isDeleting = false;
function typeWriter() {
const current = roles[roleIndex];
charIndex += isDeleting ? -1 : 1;
typeTarget.textContent = current.substring(0, charIndex);
let speed = isDeleting ? 32 : 65;
if (!isDeleting && charIndex === current.length) {
speed = 1300; isDeleting = true;
} else if (isDeleting && charIndex === 0) {
isDeleting = false;
roleIndex = (roleIndex + 1) % roles.length;
speed = 280;
}
setTimeout(typeWriter, speed);
}
typeWriter();
}
// SCROLL-TRIGGERED FADE IN
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) entry.target.classList.add('visible');
});
}, { threshold: 0.12 });
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
// NAV SCROLL STATE & SCROLL-TO-TOP VISIBILITY
const nav = document.querySelector('.nav');
const scrollTop = document.getElementById('scroll-top');
window.addEventListener('scroll', () => {
const y = window.scrollY;
nav.classList.toggle('scrolled', y > 60);
scrollTop.classList.toggle('visible', y > 400);
}, { passive: true });
// SCROLL TO TOP
if (scrollTop) {
scrollTop.addEventListener('click', () =>
window.scrollTo({ top: 0, behavior: 'smooth' })
);
}
// THEME TOGGLE
const themeBtn = document.getElementById('theme-toggle');
const html = document.documentElement;
function getPreferredTheme() {
return localStorage.getItem('theme') || 'dark';
}
function setTheme(theme) {
html.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
themeBtn.setAttribute(
'aria-label',
theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'
);
}
setTheme(getPreferredTheme());
themeBtn.addEventListener('click', () => {
const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
setTheme(next);
});
// SKILL TAG — click to Google
document.querySelectorAll('.skill-tag').forEach(tag => {
tag.addEventListener('click', () => {
window.open(`https://www.google.com/search?q=${encodeURIComponent(tag.dataset.skill)}`, '_blank');
});
tag.addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); tag.click(); }
});
});
});