-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
93 lines (82 loc) · 2.93 KB
/
Copy pathscript.js
File metadata and controls
93 lines (82 loc) · 2.93 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
/* ============================================
TYPED.JS — Hero subtitle
============================================ */
document.addEventListener("DOMContentLoaded", () => {
new Typed("#typed-output", {
strings: ["Bug Bounty Hunter.", "Security Researcher."],
typeSpeed: 100,
backSpeed: 30,
backDelay: 1800,
loop: true,
smartBackspace: true,
});
/* ============================================
NAVBAR — highlight active section on scroll
============================================ */
const sections = document.querySelectorAll("section[id]");
const navLinks = document.querySelectorAll(".nav-link");
const mainNav = document.getElementById("mainNav");
const observerOptions = {
root: null,
rootMargin: "-40% 0px -55% 0px",
threshold: 0,
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = entry.target.getAttribute("id");
navLinks.forEach((link) => {
link.classList.toggle(
"active-link",
link.getAttribute("href") === `#${id}`,
);
});
}
});
}, observerOptions);
sections.forEach((sec) => observer.observe(sec));
/* ============================================
NAVBAR — add .scrolled class after scroll
============================================ */
window.addEventListener("scroll", () => {
mainNav.classList.toggle("scrolled", window.scrollY > 50);
});
/* ============================================
SMOOTH SCROLL — close mobile nav on link click
============================================ */
navLinks.forEach((link) => {
link.addEventListener("click", () => {
const collapseEl = document.getElementById("navMenu");
const bsCollapse = bootstrap.Collapse.getInstance(collapseEl);
if (bsCollapse) bsCollapse.hide();
});
});
});
/* ============================================
STATS — count-up animation on scroll into view
============================================ */
const statNumbers = document.querySelectorAll(".stat-number");
const animateCount = (el) => {
const target = parseInt(el.getAttribute("data-target"), 10) || 0;
const duration = 2500;
const startTime = performance.now();
const step = (now) => {
const progress = Math.min((now - startTime) / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
el.textContent = Math.round(eased * target);
if (progress < 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
};
const statObserver = new IntersectionObserver(
(entries, obs) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
animateCount(entry.target);
obs.unobserve(entry.target);
}
});
},
{ threshold: 0.5 },
);
statNumbers.forEach((el) => statObserver.observe(el));