Files
blog-code/public/js/timeline-scroll-handler.js
2025-12-08 01:03:07 +08:00

173 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 全局时间线横向滚动处理脚本
// 该脚本处理所有带有 timeline-horizontal-scroll 类的元素的鼠标滚轮横向滚动
(() => {
// 存储已绑定事件的元素,防止重复绑定
const boundElements = new Set();
// 处理鼠标滚轮事件的函数
function handleWheel(e) {
// 检查是否为水平滚动容器
if (!this.classList.contains("timeline-horizontal-scroll")) {
return;
}
// 阻止默认的垂直滚动
if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
e.preventDefault();
// 将垂直滚动转换为水平滚动
this.scrollLeft += e.deltaY;
}
}
// 初始化滚动功能的函数
function initTimelineScroll() {
// 查找所有时间线水平滚动容器
var scrollContainers = document.querySelectorAll(
".timeline-horizontal-scroll",
);
scrollContainers.forEach((scrollContainer) => {
// 检查元素是否已经绑定过事件
if (boundElements.has(scrollContainer)) {
return;
}
// 检测是否为桌面端
var isDesktop = window.matchMedia("(min-width: 768px)").matches;
if (isDesktop) {
// 移除之前可能添加的事件监听器,防止重复绑定
scrollContainer.removeEventListener("wheel", handleWheel);
// 添加新的事件监听器
scrollContainer.addEventListener("wheel", handleWheel, {
passive: false,
});
// 标记元素已绑定事件
boundElements.add(scrollContainer);
}
});
}
// 清理函数,用于页面切换时清理已绑定的元素
function cleanupBoundElements() {
boundElements.clear();
}
// 页面加载完成后初始化
document.addEventListener("DOMContentLoaded", () => {
initTimelineScroll();
// 在DOM更新后再次初始化处理SWUP等SPA场景
setTimeout(initTimelineScroll, 100);
});
// 监听可能的DOM变化
if (typeof MutationObserver !== "undefined") {
var observer = new MutationObserver((mutations) => {
var shouldInit = false;
mutations.forEach((mutation) => {
if (mutation.type === "childList") {
// 检查是否有新的时间线元素被添加
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
// 检查直接添加的节点
if (node.classList?.contains("timeline-horizontal-scroll")) {
shouldInit = true;
}
// 检查节点内的子元素
if (node.querySelectorAll) {
var timelineElements = node.querySelectorAll(
".timeline-horizontal-scroll",
);
if (timelineElements.length > 0) {
shouldInit = true;
}
}
}
});
}
});
if (shouldInit) {
setTimeout(initTimelineScroll, 50);
}
});
// 观察整个文档的变化
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
// 监听页面导航事件
window.addEventListener("load", () => {
cleanupBoundElements();
setTimeout(initTimelineScroll, 100);
});
// 处理浏览器前进/后退导航
window.addEventListener("pageshow", (event) => {
if (event.persisted) {
cleanupBoundElements();
setTimeout(initTimelineScroll, 100);
}
});
// 如果使用SWUP监听其事件
if (typeof window.Swup !== "undefined") {
// 监听 SWUP 开始过渡事件
document.addEventListener("swup:transitionStart", () => {
cleanupBoundElements();
});
// 监听 SWUP 内容替换事件
document.addEventListener("swup:contentReplaced", () => {
cleanupBoundElements();
// 延迟初始化以确保DOM完全更新
setTimeout(initTimelineScroll, 50);
});
// 监听 SWUP 页面视图事件
document.addEventListener("swup:pageView", () => {
cleanupBoundElements();
setTimeout(initTimelineScroll, 100);
});
}
// 增强对 Astro 导航的支持
document.addEventListener("astro:page-load", () => {
cleanupBoundElements();
setTimeout(initTimelineScroll, 100);
});
document.addEventListener("astro:after-swap", () => {
cleanupBoundElements();
setTimeout(initTimelineScroll, 100);
});
// 暴露初始化函数到全局作用域,供其他脚本调用
window.initTimelineScrollGlobal = initTimelineScroll;
window.cleanupTimelineScroll = cleanupBoundElements;
// 立即执行一次初始化,确保在脚本加载时就绑定事件
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initTimelineScroll);
} else {
// DOM 已经加载完成
initTimelineScroll();
}
// 如果页面已经加载完成,立即初始化
if (
document.readyState === "complete" ||
document.readyState === "interactive"
) {
setTimeout(initTimelineScroll, 10);
}
})();