优化返回顶部图标
This commit is contained in:
parent
f3d7bca84c
commit
c732f72d08
@ -3,8 +3,13 @@
|
||||
<div
|
||||
v-if="visible"
|
||||
class="back-to-top-btn"
|
||||
@click="scrollToTop"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
:aria-label="t('Back to top')"
|
||||
:title="t('Back to top')"
|
||||
@click="scrollToTop"
|
||||
@keydown.enter="scrollToTop"
|
||||
@keydown.space.prevent="scrollToTop"
|
||||
>
|
||||
<!-- SVG 圆形进度条 -->
|
||||
<svg class="progress-ring" viewBox="0 0 48 48">
|
||||
@ -109,9 +114,7 @@ const getScrollInfo = (container: Element | Window): { scrollTop: number; scroll
|
||||
|
||||
// 滚动到顶部
|
||||
const scrollToTop = () => {
|
||||
const containers = registeredContainers.value.length > 0
|
||||
? registeredContainers.value
|
||||
: findScrollContainers()
|
||||
const containers = registeredContainers.value
|
||||
|
||||
containers.forEach(container => {
|
||||
if (container === window) {
|
||||
@ -129,43 +132,54 @@ const scrollToTop = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 使用 requestAnimationFrame 优化滚动处理性能
|
||||
let rafId: number | null = null
|
||||
|
||||
// 处理滚动事件
|
||||
const handleScroll = () => {
|
||||
const containers = registeredContainers.value.length > 0
|
||||
? registeredContainers.value
|
||||
: findScrollContainers()
|
||||
|
||||
if (containers.length === 0) {
|
||||
// 使用 requestAnimationFrame 节流,避免过度计算
|
||||
if (rafId !== null) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查所有容器,取最大滚动值和总高度
|
||||
let maxScrollTop = 0
|
||||
let maxProgress = 0
|
||||
|
||||
containers.forEach(container => {
|
||||
const info = getScrollInfo(container)
|
||||
const scrollTop = info.scrollTop
|
||||
const maxScroll = info.scrollHeight - info.clientHeight
|
||||
rafId = requestAnimationFrame(() => {
|
||||
const containers = registeredContainers.value
|
||||
|
||||
if (scrollTop > maxScrollTop) {
|
||||
maxScrollTop = scrollTop
|
||||
if (containers.length === 0) {
|
||||
rafId = null
|
||||
return
|
||||
}
|
||||
|
||||
// 计算当前容器的滚动进度
|
||||
if (maxScroll > 0) {
|
||||
const progress = Math.min(scrollTop / maxScroll, 1)
|
||||
if (progress > maxProgress) {
|
||||
maxProgress = progress
|
||||
// 检查所有容器,取最大滚动值和总高度
|
||||
let maxScrollTop = 0
|
||||
let maxProgress = 0
|
||||
|
||||
containers.forEach(container => {
|
||||
const info = getScrollInfo(container)
|
||||
const scrollTop = info.scrollTop
|
||||
const maxScroll = info.scrollHeight - info.clientHeight
|
||||
|
||||
if (scrollTop > maxScrollTop) {
|
||||
maxScrollTop = scrollTop
|
||||
}
|
||||
}
|
||||
|
||||
// 计算当前容器的滚动进度
|
||||
if (maxScroll > 0) {
|
||||
const progress = Math.min(scrollTop / maxScroll, 1)
|
||||
if (progress > maxProgress) {
|
||||
maxProgress = progress
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 更新滚动进度
|
||||
scrollProgress.value = maxProgress
|
||||
|
||||
// 根据最大滚动值判断是否显示按钮
|
||||
visible.value = maxScrollTop > SCROLL_THRESHOLD
|
||||
|
||||
rafId = null
|
||||
})
|
||||
|
||||
// 更新滚动进度
|
||||
scrollProgress.value = maxProgress
|
||||
|
||||
// 根据最大滚动值判断是否显示按钮
|
||||
visible.value = maxScrollTop > SCROLL_THRESHOLD
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -192,6 +206,12 @@ onUnmounted(() => {
|
||||
container.removeEventListener('scroll', handleScroll)
|
||||
})
|
||||
registeredContainers.value = []
|
||||
|
||||
// 取消待处理的 requestAnimationFrame
|
||||
if (rafId !== null) {
|
||||
cancelAnimationFrame(rafId)
|
||||
rafId = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -219,6 +239,15 @@ onUnmounted(() => {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.back-to-top-btn:focus {
|
||||
outline: 2px solid #22c55e;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.back-to-top-btn:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.progress-ring {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user