diff --git a/src/hooks/useTabScroll.ts b/src/hooks/useTabScroll.ts new file mode 100644 index 0000000..fb449af --- /dev/null +++ b/src/hooks/useTabScroll.ts @@ -0,0 +1,64 @@ +import type { NScrollbar } from 'naive-ui' +import { ref, watchEffect, type Ref } from 'vue' +import { throttle } from 'radash' + +export function useTabScroll(currentTabPath: Ref) { + const scrollbar = ref>() + const safeArea = ref(150) + + const handleTabSwitch = (distance: number) => { + scrollbar.value?.scrollTo({ + left: distance, + behavior: 'smooth' + }) + } + + const scrollToCurrentTab = () => { + nextTick(() => { + const currentTabElement = document.querySelector(`[data-tab-path="${currentTabPath.value}"]`) as HTMLElement + const tabBarScrollWrapper = document.querySelector('.tab-bar-scroller-wrapper .n-scrollbar-container') + const tabBarScrollContent = document.querySelector('.tab-bar-scroller-content') + + if (currentTabElement && tabBarScrollContent && tabBarScrollWrapper) { + const tabLeft = currentTabElement.offsetLeft + const tabBarLeft = tabBarScrollWrapper.scrollLeft + const wrapperWidth = tabBarScrollWrapper.getBoundingClientRect().width + const tabWidth = currentTabElement.getBoundingClientRect().width + const containerPR = Number.parseFloat(window.getComputedStyle(tabBarScrollContent).paddingRight) + + if (tabLeft + tabWidth + safeArea.value + containerPR > wrapperWidth + tabBarLeft) { + handleTabSwitch(tabLeft + tabWidth + containerPR - wrapperWidth + safeArea.value) + } else if (tabLeft - safeArea.value < tabBarLeft) { + handleTabSwitch(tabLeft - safeArea.value) + } + } + }) + } + + const handleScroll = throttle({ interval: 120 }, (step: number) => { + scrollbar.value?.scrollBy({ + left: step * 400, + behavior: 'smooth' + }) + }) + + const onWheel = (e: WheelEvent) => { + e.preventDefault() + if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) { + handleScroll(e.deltaY > 0 ? 1 : -1) + } + } + + watchEffect(() => { + if (currentTabPath.value) { + scrollToCurrentTab() + } + }) + + return { + scrollbar, + onWheel, + safeArea, + handleTabSwitch + } +} diff --git a/src/layouts/components/tab/TabBar.vue b/src/layouts/components/tab/TabBar.vue index 01c8469..79c61d7 100644 --- a/src/layouts/components/tab/TabBar.vue +++ b/src/layouts/components/tab/TabBar.vue @@ -1,6 +1,7 @@