优化歌词滚动流畅度

This commit is contained in:
lyswhut 2023-09-02 13:15:58 +08:00
parent 5b0f437602
commit 9b21155acf
3 changed files with 90 additions and 32 deletions

View File

@ -103,10 +103,6 @@ export default () => {
if (index < 0) return
if (flatListRef.current) {
// console.log('handleScrollToActive', index)
if (scrollCancelRef.current) {
scrollCancelRef.current()
scrollCancelRef.current = null
}
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
let offset = listLayoutInfoRef.current.spaceHeight
for (let line = 0; line < index; line++) {
@ -118,6 +114,10 @@ export default () => {
})
} catch {}
} else {
if (scrollCancelRef.current) {
scrollCancelRef.current()
scrollCancelRef.current = null
}
try {
flatListRef.current.scrollToIndex({
index,

View File

@ -143,10 +143,6 @@ export default () => {
if (index < 0) return
if (flatListRef.current) {
// console.log('handleScrollToActive', index)
if (scrollCancelRef.current) {
scrollCancelRef.current()
scrollCancelRef.current = null
}
if (scrollInfoRef.current && lineRef.current.line - lineRef.current.prevLine == 1) {
let offset = listLayoutInfoRef.current.spaceHeight
for (let line = 0; line < index; line++) {
@ -158,6 +154,10 @@ export default () => {
})
} catch {}
} else {
if (scrollCancelRef.current) {
scrollCancelRef.current()
scrollCancelRef.current = null
}
try {
flatListRef.current.scrollToIndex({
index,

View File

@ -10,17 +10,33 @@ const easeInOutQuad = (t: number, b: number, c: number, d: number): number => {
type Noop = () => void
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) {
fn()
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 cancel = false
let start = info.contentOffset.y
if (to > start) {
let maxScrollTop = info.contentSize.height - info.layoutMeasurement.height
if (to > maxScrollTop) to = maxScrollTop
@ -30,7 +46,7 @@ const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<Native
fn()
return noop
}
const change = to - start
let change = to - start
const increment = 10
if (!change) {
fn()
@ -38,32 +54,66 @@ const handleScrollY = (element: FlatList<any>, info: NativeSyntheticEvent<Native
}
let currentTime = 0
let val
let val: number
let key = Math.random()
const animateScroll = () => {
// @ts-expect-error
if (cancel || element.lx_scrollKey != key) {
fn()
element.lx_scrollTimeout = undefined
if (element.lx_scrollNextParams && currentTime > duration * 0.75) {
const [_element, info, to, duration, fn] = element.lx_scrollNextParams
info.contentOffset.y = val
clean()
handleScrollY(_element, info, to, duration, fn)
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
val = Math.trunc(easeInOutQuad(currentTime, start, change, duration))
element.scrollToOffset({ offset: val, animated: false })
if (currentTime < duration) {
setTimeout(animateScroll, increment)
element.lx_scrollTimeout = setTimeout(animateScroll, increment)
} else {
fn()
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()
}
}
}
// @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 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 timeout: NodeJS.Timeout | null
if (element.lx_scrollDelayTimeout != null) {
clearTimeout(element.lx_scrollDelayTimeout)
element.lx_scrollDelayTimeout = undefined
}
if (delay) {
let scrollCancelFn: Noop
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)
}, delay)
} else {