This commit is contained in:
2025-03-14 15:58:39 +07:00
commit abf8ab2c53
58 changed files with 11970 additions and 0 deletions

78
src/effects/homeEffect.ts Normal file
View File

@@ -0,0 +1,78 @@
"use client";
import { useEffect } from "react";
function showTypingEffect(typingNode: HTMLElement): void {
if (!typingNode) return;
const text = typingNode.innerText;
typingNode.innerText = "";
let i = 0;
const typing = setInterval(() => {
if (i < text.length) {
typingNode.innerText += text.charAt(i);
i++;
} else {
clearInterval(typing);
}
}, 100);
}
function startCarousel(containerSelector: string, loop: boolean, startDelay: number): () => void {
const containers: NodeListOf<HTMLElement> = document.querySelectorAll(`${containerSelector} .item-big`);
const DELAY: number = 120; // Thời gian delay giữa các item trong container
const INTERVAL: number = startDelay; // Thời gian trì hoãn trước khi bắt đầu carousel
// Cập nhật trạng thái item (active, previous)
const updateItemState = (items: NodeListOf<HTMLElement>, activeIndex: number): number => {
const nextIndex: number = (activeIndex + 1) % items.length;
resetItemsState(items); // Xóa các trạng thái 'active' và 'previous'
markItemState(items, activeIndex, nextIndex); // Đánh dấu item hiện tại và item tiếp theo
return nextIndex;
};
// Hàm reset các trạng thái 'active' và 'previous' của các items
const resetItemsState = (items: NodeListOf<HTMLElement>): void => {
items.forEach((item: HTMLElement) => {
item.classList.remove('active', 'previous');
});
};
// Hàm đánh dấu item hiện tại và item tiếp theo
const markItemState = (items: NodeListOf<HTMLElement>, activeIndex: number, nextIndex: number): void => {
items[activeIndex].classList.add('previous');
items[nextIndex].classList.add('active');
};
// Hàm xử lý vòng lặp carousel cho mỗi container
const processContainer = (container: HTMLElement, index: number): void => {
const items: NodeListOf<HTMLElement> = container.querySelectorAll('.item');
let activeIndex: number = Array.from(items).findIndex((item: HTMLElement) => item.classList.contains('active')) || 0;
setTimeout(() => {
activeIndex = updateItemState(items, activeIndex);
// Nếu không muốn loop và đã đến item cuối, dừng vòng lặp
if (!loop && activeIndex === items.length - 1) {
clearInterval(intervalId);
}
}, index * DELAY); // Delay riêng cho mỗi container
};
// Hàm xử lý tất cả các container
const processContainers = (): void => {
containers.forEach((container: HTMLElement, index: number) => {
processContainer(container, index);
});
};
// Chạy vòng lặp carousel theo khoảng thời gian INTERVAL
const intervalId: NodeJS.Timeout = setInterval(processContainers, INTERVAL);
// Trả về hàm dừng vòng lặp khi cần
return () => clearInterval(intervalId);
}
export const homePageEffect = {
showTypingEffect,
startCarousel
};