mirror of
https://github.com/ION606/ion606.github.io.git
synced 2026-05-14 22:16:59 +00:00
205 lines
5.3 KiB
JavaScript
205 lines
5.3 KiB
JavaScript
// Initialize animations and interactions
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
createStars();
|
|
initObservers();
|
|
initKonamiCode();
|
|
});
|
|
|
|
function createStars() {
|
|
const starfield = document.getElementById("starfield");
|
|
starfield.innerHTML = "";
|
|
|
|
for (let i = 0; i < 200; i++) {
|
|
const star = document.createElement("div");
|
|
star.className = "star";
|
|
star.style.width = Math.random() * 3 + "px";
|
|
star.style.height = star.style.width;
|
|
star.style.left = Math.random() * 100 + "%";
|
|
star.style.top = Math.random() * 100 + "%";
|
|
star.style.animationDuration = Math.random() * 3 + 1 + "s";
|
|
starfield.appendChild(star);
|
|
}
|
|
}
|
|
|
|
function initObservers() {
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.style.opacity = 1;
|
|
entry.target.style.transform = "translateY(0)";
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.1 }
|
|
);
|
|
|
|
document.querySelectorAll(".section, .timeline-item").forEach((el) => {
|
|
observer.observe(el);
|
|
});
|
|
}
|
|
|
|
function initKonamiCode() {
|
|
const konamiCode = [
|
|
"ArrowUp",
|
|
"ArrowUp",
|
|
"ArrowDown",
|
|
"ArrowDown",
|
|
"ArrowLeft",
|
|
"ArrowRight",
|
|
"ArrowLeft",
|
|
"ArrowRight",
|
|
"b",
|
|
"a",
|
|
];
|
|
let index = 0;
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
e.key === konamiCode[index] ? index++ : (index = 0);
|
|
if (index === konamiCode.length) {
|
|
document.body.classList.add("konami-mode");
|
|
const ufo = document.querySelector(".ufo");
|
|
ufo.style.animation = "flyby 15s linear infinite";
|
|
}
|
|
});
|
|
}
|
|
|
|
// create starfield effect
|
|
const createStarfield = () => {
|
|
const starfield = document.querySelector("#starfield");
|
|
const numStars = 150;
|
|
for (let i = 0; i < numStars; i++) {
|
|
const star = document.createElement("div");
|
|
star.classList.add("star");
|
|
// randomize size and position
|
|
const size = Math.random() * 3 + 1;
|
|
star.style.width = `${size}px`;
|
|
star.style.height = `${size}px`;
|
|
star.style.top = `${Math.random() * 100}vh`;
|
|
star.style.left = `${Math.random() * 100}vw`;
|
|
// random duration for twinkling
|
|
star.style.setProperty("--duration", `${Math.random() * 3 + 2}s`);
|
|
// add click event to form constellations
|
|
star.addEventListener("click", (e) => {
|
|
console.log("star clicked at", e.pageX, e.pageY);
|
|
});
|
|
starfield.appendChild(star);
|
|
}
|
|
};
|
|
|
|
// implement typewriter effect for hero section
|
|
function typewriterEffect() {
|
|
const el = document.querySelector(".typing-text");
|
|
const text = el.getAttribute("data-text");
|
|
el.innerHTML = ""; // Clear any existing content
|
|
|
|
// Create a span for the typed text
|
|
const textSpan = document.createElement("span");
|
|
textSpan.className = "typed-text";
|
|
el.appendChild(textSpan);
|
|
|
|
// Create a blinking caret appended after the text
|
|
const caretSpan = document.createElement("span");
|
|
caretSpan.className = "typing-cursor";
|
|
el.appendChild(caretSpan);
|
|
|
|
let index = 0;
|
|
const speed = 100; // ms/char
|
|
|
|
function type() {
|
|
if (index < text.length) {
|
|
textSpan.textContent += text.charAt(index);
|
|
index++;
|
|
setTimeout(type, speed);
|
|
} else setTimeout(() => caretSpan.remove(), 2000);
|
|
}
|
|
type();
|
|
}
|
|
|
|
const createParticleEffect = () => {
|
|
const particles = document.createElement("div");
|
|
particles.style.position = "fixed";
|
|
particles.style.top = `${Math.random() * window.innerHeight}px`;
|
|
particles.style.left = `${Math.random() * window.innerWidth}px`;
|
|
particles.style.width = "5px";
|
|
particles.style.height = "5px";
|
|
particles.style.background = "var(--primary)";
|
|
particles.style.borderRadius = "50%";
|
|
particles.style.opacity = "0.8";
|
|
particles.style.pointerEvents = "none";
|
|
particles.style.transition = "opacity 1s ease-out";
|
|
document.body.appendChild(particles);
|
|
setTimeout(() => {
|
|
particles.style.opacity = "0";
|
|
}, 50);
|
|
setTimeout(() => {
|
|
particles.remove();
|
|
}, 1000);
|
|
};
|
|
|
|
// implement particle effect on scroll
|
|
const particleEffectOnScroll = () => {
|
|
window.addEventListener("scroll", () => createParticleEffect);
|
|
};
|
|
|
|
// konami code detection for UFO easter egg
|
|
let keyBuffer = [];
|
|
|
|
// launch UFO easter egg
|
|
const launchUFO = () => {
|
|
const ufo = document.createElement("div");
|
|
ufo.classList.add("ufo");
|
|
document.body.appendChild(ufo);
|
|
// remove UFO after animation
|
|
ufo.addEventListener("animationend", () => {
|
|
ufo.remove();
|
|
});
|
|
};
|
|
|
|
// intersection observer for sections
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.style.opacity = 1;
|
|
entry.target.style.transform = "translateY(0)";
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.1 }
|
|
);
|
|
|
|
document.querySelectorAll(".section").forEach((section, index) => {
|
|
observer.observe(section);
|
|
section.style.animationDelay = `${index * 0.2}s`;
|
|
});
|
|
|
|
createStarfield();
|
|
typewriterEffect();
|
|
particleEffectOnScroll();
|
|
|
|
let hovered = false;
|
|
const modTitle = document.querySelector("#moduleTitle"),
|
|
modules = modTitle.parentElement.querySelectorAll(".module");
|
|
|
|
modules.forEach((el) => {
|
|
el.addEventListener("mouseenter", () => el.classList.add("hovered"));
|
|
el.addEventListener("mouseleave", () => el.classList.remove("hovered"));
|
|
});
|
|
|
|
modTitle.addEventListener("mouseenter", async () => {
|
|
if (hovered) return;
|
|
hovered = true;
|
|
|
|
for (const el of modules) {
|
|
el.classList.add("hovered");
|
|
|
|
// anim is .2 seconds
|
|
setTimeout(() => el.classList.remove("hovered"), 200);
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
}
|
|
});
|
|
|
|
modTitle.addEventListener("mouseleave", () => (hovered = false));
|