mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-12-02 11:17:46 +08:00
68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
import { isClient } from '@vueuse/core'
|
|
import { throttleAndDebounce } from '../utils'
|
|
|
|
const threshold = 960
|
|
|
|
const cubic = (value: number): number => value ** 3
|
|
const easeInOutCubic = (value: number): number =>
|
|
value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2
|
|
|
|
export const useBackTop = (offset = 200) => {
|
|
const shouldShow = ref(false)
|
|
const throttleResize = throttleAndDebounce(onResize, 300)
|
|
const throttleScroll = throttleAndDebounce(onScroll, 160)
|
|
|
|
onMounted(() => {
|
|
if (!isClient) return
|
|
onResize()
|
|
onScroll()
|
|
window.addEventListener('resize', throttleResize)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
if (!isClient) return
|
|
window.removeEventListener('resize', throttleResize)
|
|
window.removeEventListener('scroll', throttleScroll)
|
|
})
|
|
|
|
const scrollToTop = () => {
|
|
const beginTime = Date.now()
|
|
const beginValue = document.documentElement.scrollTop
|
|
const rAF = window.requestAnimationFrame
|
|
const frameFunc = () => {
|
|
const progress = (Date.now() - beginTime) / 500
|
|
if (progress < 1) {
|
|
document.documentElement.scrollTop =
|
|
beginValue * (1 - easeInOutCubic(progress))
|
|
rAF(frameFunc)
|
|
} else {
|
|
document.documentElement.scrollTop = 0
|
|
}
|
|
}
|
|
rAF(frameFunc)
|
|
}
|
|
|
|
function onResize() {
|
|
if (!isClient) return
|
|
|
|
const { clientWidth } = document.body
|
|
|
|
if (clientWidth < threshold) {
|
|
window.addEventListener('scroll', throttleScroll)
|
|
} else {
|
|
window.removeEventListener('scroll', throttleScroll)
|
|
}
|
|
}
|
|
|
|
function onScroll() {
|
|
if (!isClient) return
|
|
shouldShow.value = document.documentElement.scrollTop > offset
|
|
}
|
|
|
|
return {
|
|
shouldShow,
|
|
scrollToTop,
|
|
}
|
|
}
|