-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
284 lines (238 loc) · 9.97 KB
/
script.js
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// scripts.js
document.addEventListener('DOMContentLoaded', function() {
/* ============================
Smooth Scrolling for Anchor Links
============================ */
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const targetElement = document.querySelector(this.getAttribute('href'));
if (targetElement) {
targetElement.scrollIntoView({
behavior: 'smooth'
});
}
// If on mobile, close the navbar after clicking a link
const navbar = document.querySelector('.navbar');
const navLinks = document.getElementById('nav-links');
if (navLinks.classList.contains('active')) {
navLinks.classList.remove('active');
const hamburger = document.getElementById('hamburger');
hamburger.classList.remove('active');
}
});
});
/* ============================
Responsive Navbar with Hamburger Menu
============================ */
const navbar = document.querySelector('.navbar'); // Select the navbar element
const hamburger = document.getElementById('hamburger'); // Select the hamburger menu
const navLinks = document.getElementById('nav-links'); // Select the nav links
let hideTimeout;
// Function to hide the navbar (desktop only)
function hideNavbar() {
// Only hide navbar on non-mobile devices
if (window.innerWidth > 768) {
navbar.classList.add('hidden');
}
}
// Function to show the navbar
function showNavbar() {
navbar.classList.remove('hidden');
}
// Toggle hamburger menu
hamburger.addEventListener('click', function() {
navLinks.classList.toggle('active');
hamburger.classList.toggle('active');
});
// Initially, set a timeout to hide the navbar after 2 seconds (desktop only)
hideTimeout = setTimeout(hideNavbar, 2000);
// Event Listener: Show navbar when user hovers near the top 50px of the page (desktop only)
document.addEventListener('mousemove', function(e) {
if (window.innerWidth > 768) { // Only apply on desktop
if (e.clientY < 50) { // If the mouse Y-coordinate is within 50px from the top
showNavbar(); // Show the navbar
clearTimeout(hideTimeout); // Clear any existing hide timeout
} else {
// If the navbar is visible and the mouse moves away from the top, set a timeout to hide it
if (!navbar.classList.contains('hidden')) {
hideTimeout = setTimeout(hideNavbar, 2000); // Hide after 2 seconds
}
}
}
});
// Optional: Show navbar when the user scrolls up (desktop only)
let lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
window.addEventListener('scroll', function() {
if (window.innerWidth > 768) { // Only apply on desktop
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop < lastScrollTop) {
// User scrolled up
showNavbar();
clearTimeout(hideTimeout);
hideTimeout = setTimeout(hideNavbar, 2000); // Hide again after 2 seconds
} else if (scrollTop > lastScrollTop) {
// User scrolled down
hideNavbar();
}
lastScrollTop = scrollTop;
}
});
/* ============================
Modal Functionality
============================ */
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
/* ============================
Scroll To Top Button Functionality
============================ */
const scrollToTopBtn = document.getElementById("scrollToTopBtn");
// Show the button when the user scrolls down 300px from the top
window.addEventListener('scroll', function() {
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 300) {
scrollToTopBtn.style.display = "block";
} else {
scrollToTopBtn.style.display = "none";
}
});
// Scroll to the top of the page when the button is clicked
scrollToTopBtn.addEventListener('click', function() {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
/* ============================
Skills Animation Functionality
============================ */
// Function to animate the skill bars
function animateSkillBars() {
const skillBars = document.querySelectorAll('.skill-bar span');
skillBars.forEach(skillBar => {
const targetWidth = skillBar.getAttribute('data-percent'); // Get the target width from data attribute
let currentWidth = 0;
function animate() {
if (currentWidth < targetWidth) {
currentWidth += 1; // Increase width incrementally
skillBar.style.width = currentWidth + '%';
requestAnimationFrame(animate); // Continue animation
} else {
skillBar.style.width = targetWidth + '%'; // Ensure it reaches the final width
}
}
animate(); // Start the animation
});
}
// Function to observe when the skills section enters the viewport
function observeSkillsSection() {
const skillsSection = document.querySelector('#skills');
// Create an IntersectionObserver instance
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) { // If the section is in view
animateSkillBars(); // Trigger the animation
observer.unobserve(skillsSection); // Stop observing after animation is triggered
}
});
}, { threshold: 0.1 }); // Trigger when 10% of the section is in view
// Start observing the skills section
observer.observe(skillsSection);
}
// Trigger the observer
observeSkillsSection();
/* ============================
Background Canvas Animation (Optional)
============================ */
const canvas = document.getElementById('backgroundCanvas');
const ctx = canvas.getContext('2d');
// Resize the canvas to fill the window
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initParticles(); // Reinitialize particles on resize
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Particle Class
class Particle {
constructor(x, y, dx, dy, size, color) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.size = size;
this.color = color;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
ctx.fillStyle = this.color;
ctx.fill();
}
update() {
if (this.x + this.size > canvas.width || this.x - this.size < 0) {
this.dx = -this.dx;
}
if (this.y + this.size > canvas.height || this.y - this.size < 0) {
this.dy = -this.dy;
}
this.x += this.dx;
this.y += this.dy;
this.draw();
}
}
// mobile
document.addEventListener('DOMContentLoaded', () => {
const hamburger = document.querySelector('.hamburger');
const navbar = document.querySelector('.navbar');
const overlay = document.querySelector('.navbar-overlay');
hamburger?.addEventListener('click', () => {
navbar.classList.toggle('active');
overlay.classList.toggle('active');
});
overlay?.addEventListener('click', () => {
navbar.classList.remove('active');
overlay.classList.remove('active');
});
});
// Initialize Particles
let particlesArray = [];
const colorsParticles = ['rgba(26, 188, 156, 0.8)', 'rgba(52, 152, 219, 0.8)', 'rgba(155, 89, 182, 0.8)'];
function initParticles() {
particlesArray = [];
// Adjust number of particles based on screen size for performance
const numberOfParticles = Math.floor((canvas.width * canvas.height) / 20000); // Reduced density for mobile
for (let i = 0; i < numberOfParticles; i++) {
let size = Math.random() * 3 + 1;
let x = Math.random() * (canvas.width - size * 2) + size;
let y = Math.random() * (canvas.height - size * 2) + size;
let dx = (Math.random() - 0.5) * 1;
let dy = (Math.random() - 0.5) * 1;
let color = colorsParticles[Math.floor(Math.random() * colorsParticles.length)];
particlesArray.push(new Particle(x, y, dx, dy, size, color));
}
}
// Animate Particles
function animateParticles() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
particlesArray.forEach(particle => particle.update());
requestAnimationFrame(animateParticles);
}
initParticles();
animateParticles();
});