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:
parent
38db6e6744
commit
84eafb8746
15 changed files with 382 additions and 384 deletions
67
js/hero-animations.js
Normal file
67
js/hero-animations.js
Normal 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
17
js/loading-screen.js
Normal 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
74
js/menu-animations.js
Normal 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
107
js/page-transitions.js
Normal 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");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue