Update 'about.html' to correct team member numbering and enhance 'index.html' with preloading of critical resources, optimized images, and deferred script loading for improved performance. Modify 'package.json' to include minification in the build script and enable JIT mode in 'tailwind.config.js'.

This commit is contained in:
George Birikorang 2025-09-19 10:02:20 -07:00
parent 38db6e6744
commit 84eafb8746
15 changed files with 382 additions and 384 deletions

67
js/hero-animations.js Normal file
View file

@ -0,0 +1,67 @@
// Hero image transitions and animations
document.addEventListener("DOMContentLoaded", function () {
// Enhanced slide + zoom hero image transitions
const imgs = [
"assets/images/optimized/room_optimized.jpg",
"assets/images/optimized/chair_optimized.jpg",
"assets/images/optimized/google_optimized.jpg",
];
const currentImg = document.getElementById("currentImg");
const nextImg = document.getElementById("nextImg");
if (currentImg && nextImg) {
let currentIndex = 0;
let isTransitioning = false;
// Alternate slide directions for dynamic effect
const slideDirections = ["left", "right"];
let slideIndex = 0;
function performSlideZoomTransition() {
if (isTransitioning) return;
isTransitioning = true;
// Get next image index
const nextIndex = (currentIndex + 1) % imgs.length;
const slideDirection =
slideDirections[slideIndex % slideDirections.length];
slideIndex++;
// Set up next image
nextImg.src = imgs[nextIndex];
nextImg.style.opacity = "1";
// Apply animations based on slide direction
if (slideDirection === "left") {
// Current slides out left, next zooms in from right
currentImg.style.animation = "slideOutLeft 1s ease-in-out forwards";
nextImg.style.animation = "zoomInFromRight 1s ease-in-out forwards";
} else {
// Current slides out right, next zooms in from left
currentImg.style.animation = "slideOutRight 1s ease-in-out forwards";
nextImg.style.animation = "zoomInFromLeft 1s ease-in-out forwards";
}
// After animation completes, swap the images
setTimeout(() => {
// Swap the images
currentImg.src = imgs[nextIndex];
currentImg.style.animation = "";
currentImg.style.transform = "";
currentImg.style.opacity = "1";
// Reset next image
nextImg.style.animation = "";
nextImg.style.transform = "";
nextImg.style.opacity = "0";
currentIndex = nextIndex;
isTransitioning = false;
}, 1000); // Match animation duration
}
// Start the transition cycle
setInterval(performSlideZoomTransition, 10000); // Every 10 seconds for better viewing
}
});

17
js/loading-screen.js Normal file
View file

@ -0,0 +1,17 @@
// Loading screen functionality
document.addEventListener("DOMContentLoaded", function () {
// Loading screen with improved timing
window.addEventListener("load", () => {
const loadingScreen = document.getElementById("loadingScreen");
if (loadingScreen) {
// Show loading screen briefly, then fade out just before animations start
setTimeout(() => {
loadingScreen.style.transition = "opacity 0.3s ease-out";
loadingScreen.style.opacity = "0";
setTimeout(() => {
loadingScreen.style.display = "none";
}, 300);
}, 400); // Reduced from 1000ms to 400ms to sync with animations
}
});
});

74
js/menu-animations.js Normal file
View file

@ -0,0 +1,74 @@
// Menu toggle functionality and animations
document.addEventListener("DOMContentLoaded", function () {
const menuToggle = document.getElementById("menuToggle");
const navMenu = document.getElementById("navMenu");
const menuWrap = document.getElementById("menuWrap");
const menuGrid = document.getElementById("menuGrid");
const menuGridMobile = document.getElementById("menuGridMobile");
if (menuToggle && navMenu) {
let isMenuOpen = false;
menuToggle.addEventListener("click", () => {
if (isMenuOpen) {
// Close menu
navMenu.classList.add("hidden");
if (menuWrap) menuWrap.classList.remove("open");
isMenuOpen = false;
} else {
// Open menu
navMenu.classList.remove("hidden");
if (menuWrap) menuWrap.classList.add("open");
isMenuOpen = true;
}
});
// Close menu when clicking outside
document.addEventListener("click", (e) => {
if (!menuToggle.contains(e.target) && !navMenu.contains(e.target)) {
navMenu.classList.add("hidden");
if (menuWrap) menuWrap.classList.remove("open");
isMenuOpen = false;
}
});
}
// Custom cursor functionality
const customCursor = document.getElementById("customCursor");
if (customCursor) {
// Hide default cursor
document.body.style.cursor = "none";
// Follow mouse movement
document.addEventListener("mousemove", (e) => {
customCursor.style.left = e.clientX - 12 + "px";
customCursor.style.top = e.clientY - 12 + "px";
});
// Menu grid hover effects
if (menuGrid) {
menuGrid.addEventListener("mouseenter", () => {
customCursor.style.borderColor = "#B03037";
customCursor.style.transform = "scale(1.5)";
customCursor.style.animation = "spin 0.5s linear infinite";
});
menuGrid.addEventListener("mouseleave", () => {
customCursor.style.borderColor = "#B03037";
customCursor.style.transform = "scale(1)";
customCursor.style.animation = "none";
});
}
}
// Add spin animation for cursor
const style = document.createElement("style");
style.textContent = `
@keyframes spin {
from { transform: scale(1.5) rotate(0deg); }
to { transform: scale(1.5) rotate(360deg); }
}
`;
document.head.appendChild(style);
});

107
js/page-transitions.js Normal file
View file

@ -0,0 +1,107 @@
// Page transition functionality
document.addEventListener("DOMContentLoaded", function () {
// Top/Bottom curtain transition system
const curtainTop =
document.getElementById("pageCurtainTop") ||
(() => {
const div = document.createElement("div");
div.id = "pageCurtainTop";
div.className =
"fixed inset-x-0 top-0 h-1/2 z-50 transform -translate-y-full transition-transform duration-600 ease-in-out";
div.style.background = "linear-gradient(0deg, #b03037, #8a252a)";
document.body.appendChild(div);
return div;
})();
const curtainBottom =
document.getElementById("pageCurtainBottom") ||
(() => {
const div = document.createElement("div");
div.id = "pageCurtainBottom";
div.className =
"fixed inset-x-0 bottom-0 h-1/2 z-50 transform translate-y-full transition-transform duration-600 ease-in-out";
div.style.background = "linear-gradient(180deg, #b03037, #8a252a)";
document.body.appendChild(div);
return div;
})();
// Add entrance animation class
document.body.style.animation = "pageEnter 0.6s ease-out";
document.querySelectorAll("a[data-trans]").forEach((a) => {
a.addEventListener("click", (e) => {
const href = a.getAttribute("href");
if (!href || href.startsWith("#")) return;
e.preventDefault();
// Collect elements that had delayed entrance and fade them out in reverse order
const animatedEls = Array.from(
document.querySelectorAll('[style*="animation-delay"]')
).map((el) => {
const m = (el.getAttribute("style") || "").match(
/animation-delay:\s*([0-9.]+)s/
);
const delay = m ? parseFloat(m[1]) : 0;
return { el, delay };
});
const sorted = animatedEls
.sort((a, b) => b.delay - a.delay)
.map((item, idx) => ({ ...item, order: idx }));
sorted.forEach((item) => {
setTimeout(() => {
item.el.style.animation = "staggerFadeOut 260ms ease-out forwards";
}, item.order * 50);
});
const totalStaggerTime = (sorted.length - 1) * 50 + 260 + 130;
setTimeout(() => {
// Crossfade + tiny zoom of the whole page (longer)
document.body.style.animation = "pageExit 900ms ease forwards";
setTimeout(() => {
location.href = href;
}, 920);
}, totalStaggerTime);
});
});
// Hide curtains and close nav just before page is cached (prevents blank back step)
window.addEventListener("pagehide", () => {
if (curtainTop) curtainTop.style.transform = "translateY(-100%)";
if (curtainBottom) curtainBottom.style.transform = "translateY(100%)";
const navEl = document.getElementById("navMenu");
const gridEl = document.getElementById("menuGrid");
if (navEl) navEl.classList.add("hidden");
const wrapEl = document.getElementById("menuWrap");
if (wrapEl) wrapEl.classList.remove("open");
});
// Handle back/forward navigation
window.addEventListener("pageshow", function (event) {
if (event.persisted) {
// Page was loaded from cache (back/forward)
window.location.reload();
}
});
// Ensure back/forward navigation (bfcache) shows a clean page
window.addEventListener("pageshow", () => {
const loadingScreen = document.getElementById("loadingScreen");
if (loadingScreen) {
loadingScreen.style.display = "none";
loadingScreen.style.opacity = "0";
}
const ct = document.getElementById("pageCurtainTop");
const cb = document.getElementById("pageCurtainBottom");
if (ct) ct.style.transform = "translateY(-100%)";
if (cb) cb.style.transform = "translateY(100%)";
// Close nav if it was left open and reset grid icon
const navMenuEl = document.getElementById("navMenu");
const wrapEl2 = document.getElementById("menuWrap");
if (navMenuEl) navMenuEl.classList.add("hidden");
if (wrapEl2) wrapEl2.classList.remove("open");
});
});