mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-05-23 22:37:41 +08:00
优化歌词滚动流畅度
This commit is contained in:
parent
5b0f437602
commit
9b21155acf
@ -103,10 +103,6 @@ export default () => {
|
|||||||
if (index < 0) return
|
if (index < 0) return
|
||||||
if (flatListRef.current) {
|
if (flatListRef.current) {
|
||||||
// console.log('handleScrollToActive', index)
|
// console.log('handleScrollToActive', index)
|
||||||
if (scrollCancelRef.current) {
|
|
||||||
scrollCancelRef.current()
|
|
||||||
scrollCancelRef.current = null
|
|
||||||
}
|
|
||||||
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
|
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
|
||||||
let offset = listLayoutInfoRef.current.spaceHeight
|
let offset = listLayoutInfoRef.current.spaceHeight
|
||||||
for (let line = 0; line < index; line++) {
|
for (let line = 0; line < index; line++) {
|
||||||
@ -118,6 +114,10 @@ export default () => {
|
|||||||
})
|
})
|
||||||
} catch {}
|
} catch {}
|
||||||
} else {
|
} else {
|
||||||
|
if (scrollCancelRef.current) {
|
||||||
|
scrollCancelRef.current()
|
||||||
|
scrollCancelRef.current = null
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
flatListRef.current.scrollToIndex({
|
flatListRef.current.scrollToIndex({
|
||||||
index,
|
index,
|
||||||
|
@ -143,10 +143,6 @@ export default () => {
|
|||||||
if (index < 0) return
|
if (index < 0) return
|
||||||
if (flatListRef.current) {
|
if (flatListRef.current) {
|
||||||
// console.log('handleScrollToActive', index)
|
// console.log('handleScrollToActive', index)
|
||||||
if (scrollCancelRef.current) {
|
|
||||||
scrollCancelRef.current()
|
|
||||||
scrollCancelRef.current = null
|
|
||||||
}
|
|
||||||
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
|
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
|
||||||
let offset = listLayoutInfoRef.current.spaceHeight
|
let offset = listLayoutInfoRef.current.spaceHeight
|
||||||
for (let line = 0; line < index; line++) {
|
for (let line = 0; line < index; line++) {
|
||||||
@ -158,6 +154,10 @@ export default () => {
|
|||||||
})
|
})
|
||||||
} catch {}
|
} catch {}
|
||||||
} else {
|
} else {
|
||||||
|
if (scrollCancelRef.current) {
|
||||||
|
scrollCancelRef.current()
|
||||||
|
scrollCancelRef.current = null
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
flatListRef.current.scrollToIndex({
|
flatListRef.current.scrollToIndex({
|
||||||
index,
|
index,
|
||||||
|
@ -10,17 +10,33 @@ const easeInOutQuad = (t: number, b: number, c: number, d: number): number => {
|
|||||||
type Noop = () => void
|
type Noop = () => void
|
||||||
const noop: Noop = () => {}
|
const noop: Noop = () => {}
|
||||||
|
|
||||||
const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<NativeScrollEvent>['nativeEvent'], to: number, duration = 300, fn = noop): Noop => {
|
type ScrollElement<T> = {
|
||||||
|
lx_scrollLockKey?: number
|
||||||
|
lx_scrollNextParams?: [ScrollElement<FlatList<any>>, NativeSyntheticEvent<NativeScrollEvent>['nativeEvent'], number, number, Noop]
|
||||||
|
lx_scrollTimeout?: NodeJS.Timeout
|
||||||
|
lx_scrollDelayTimeout?: NodeJS.Timeout
|
||||||
|
} & T
|
||||||
|
|
||||||
|
const handleScrollY = (element: ScrollElement<FlatList<any>>, info: NativeSyntheticEvent<NativeScrollEvent>['nativeEvent'], to: number, duration = 300, fn = noop): Noop => {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
fn()
|
fn()
|
||||||
return noop
|
return noop
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = Math.random()
|
const clean = () => {
|
||||||
|
element.lx_scrollLockKey = undefined
|
||||||
|
element.lx_scrollNextParams = undefined
|
||||||
|
if (element.lx_scrollTimeout) clearTimeout(element.lx_scrollTimeout)
|
||||||
|
element.lx_scrollTimeout = undefined
|
||||||
|
}
|
||||||
|
if (element.lx_scrollLockKey) {
|
||||||
|
element.lx_scrollNextParams = [element, info, to, duration, fn]
|
||||||
|
element.lx_scrollLockKey = -1
|
||||||
|
return clean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const start = info.contentOffset.y
|
let start = info.contentOffset.y
|
||||||
let cancel = false
|
|
||||||
if (to > start) {
|
if (to > start) {
|
||||||
let maxScrollTop = info.contentSize.height - info.layoutMeasurement.height
|
let maxScrollTop = info.contentSize.height - info.layoutMeasurement.height
|
||||||
if (to > maxScrollTop) to = maxScrollTop
|
if (to > maxScrollTop) to = maxScrollTop
|
||||||
@ -30,7 +46,7 @@ const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<Native
|
|||||||
fn()
|
fn()
|
||||||
return noop
|
return noop
|
||||||
}
|
}
|
||||||
const change = to - start
|
let change = to - start
|
||||||
const increment = 10
|
const increment = 10
|
||||||
if (!change) {
|
if (!change) {
|
||||||
fn()
|
fn()
|
||||||
@ -38,32 +54,66 @@ const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<Native
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentTime = 0
|
let currentTime = 0
|
||||||
let val
|
let val: number
|
||||||
|
let key = Math.random()
|
||||||
|
|
||||||
const animateScroll = () => {
|
const animateScroll = () => {
|
||||||
// @ts-expect-error
|
element.lx_scrollTimeout = undefined
|
||||||
if (cancel || element.lx_scrollKey != key) {
|
if (element.lx_scrollNextParams && currentTime > duration * 0.75) {
|
||||||
fn()
|
const [_element, info, to, duration, fn] = element.lx_scrollNextParams
|
||||||
|
info.contentOffset.y = val
|
||||||
|
clean()
|
||||||
|
handleScrollY(_element, info, to, duration, fn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// if (element.lx_scrollLockKey != key) {
|
||||||
|
// if (element.lx_scrollNextParams) {
|
||||||
|
// // element.lx_scrollNextParams[1].contentOffset.y = val
|
||||||
|
// // handleScrollY(element.lx_scrollNextParams[0], element.lx_scrollNextParams[1], element.lx_scrollNextParams[2], element.lx_scrollNextParams[3], element.lx_scrollNextParams[4])
|
||||||
|
// start = val
|
||||||
|
// info = element.lx_scrollNextParams[1]
|
||||||
|
// to = element.lx_scrollNextParams[2]
|
||||||
|
// fn = element.lx_scrollNextParams[4]
|
||||||
|
// if (to > start) {
|
||||||
|
// let maxScrollTop = info.contentSize.height - info.layoutMeasurement.height
|
||||||
|
// if (to > maxScrollTop) to = maxScrollTop
|
||||||
|
// } else if (to < start) {
|
||||||
|
// if (to < 0) to = 0
|
||||||
|
// } else {
|
||||||
|
// clean()
|
||||||
|
// fn()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// change = to - val
|
||||||
|
|
||||||
|
// element.lx_scrollLockKey = key
|
||||||
|
// } else {
|
||||||
|
// fn()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// }
|
||||||
currentTime += increment
|
currentTime += increment
|
||||||
val = Math.trunc(easeInOutQuad(currentTime, start, change, duration))
|
val = Math.trunc(easeInOutQuad(currentTime, start, change, duration))
|
||||||
element.scrollToOffset({ offset: val, animated: false })
|
element.scrollToOffset({ offset: val, animated: false })
|
||||||
if (currentTime < duration) {
|
if (currentTime < duration) {
|
||||||
setTimeout(animateScroll, increment)
|
element.lx_scrollTimeout = setTimeout(animateScroll, increment)
|
||||||
} else {
|
} else {
|
||||||
|
if (element.lx_scrollNextParams) {
|
||||||
|
const [_element, to, duration, fn] = element.lx_scrollNextParams
|
||||||
|
info.contentOffset.y = val
|
||||||
|
clean()
|
||||||
|
handleScrollY(_element, to, duration, fn)
|
||||||
|
} else {
|
||||||
|
clean()
|
||||||
fn()
|
fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @ts-expect-error
|
|
||||||
element.lx_scrollKey = key
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
animateScroll()
|
|
||||||
})
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
cancel = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
element.lx_scrollLockKey = key
|
||||||
|
animateScroll()
|
||||||
|
|
||||||
|
return clean
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 设置滚动条位置
|
* 设置滚动条位置
|
||||||
@ -73,16 +123,24 @@ const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<Native
|
|||||||
* @param fn 滚动完成后的回调
|
* @param fn 滚动完成后的回调
|
||||||
* @param delay 延迟执行时间
|
* @param delay 延迟执行时间
|
||||||
*/
|
*/
|
||||||
export const scrollTo = (element: FlatList<any>, info: NativeSyntheticEvent<NativeScrollEvent>['nativeEvent'], to: number, duration = 300, fn = () => {}, delay = 0): () => void => {
|
export const scrollTo = (element: ScrollElement<FlatList<any>>, info: NativeSyntheticEvent<NativeScrollEvent>['nativeEvent'], to: number, duration = 300, fn = () => {}, delay = 0): () => void => {
|
||||||
let cancelFn: () => void
|
let cancelFn: () => void
|
||||||
let timeout: NodeJS.Timeout | null
|
if (element.lx_scrollDelayTimeout != null) {
|
||||||
|
clearTimeout(element.lx_scrollDelayTimeout)
|
||||||
|
element.lx_scrollDelayTimeout = undefined
|
||||||
|
}
|
||||||
if (delay) {
|
if (delay) {
|
||||||
let scrollCancelFn: Noop
|
let scrollCancelFn: Noop
|
||||||
cancelFn = () => {
|
cancelFn = () => {
|
||||||
timeout == null ? scrollCancelFn?.() : clearTimeout(timeout)
|
if (element.lx_scrollDelayTimeout == null) {
|
||||||
|
scrollCancelFn?.()
|
||||||
|
} else {
|
||||||
|
clearTimeout(element.lx_scrollDelayTimeout)
|
||||||
|
element.lx_scrollDelayTimeout = undefined
|
||||||
}
|
}
|
||||||
timeout = setTimeout(() => {
|
}
|
||||||
timeout = null
|
element.lx_scrollDelayTimeout = setTimeout(() => {
|
||||||
|
element.lx_scrollDelayTimeout = undefined
|
||||||
scrollCancelFn = handleScrollY(element, info, to, duration, fn)
|
scrollCancelFn = handleScrollY(element, info, to, duration, fn)
|
||||||
}, delay)
|
}, delay)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user