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
442c7c6a23
commit
64f128cb55
@ -3,7 +3,7 @@ import { Text, type TextProps as _TextProps, StyleSheet, Animated, type ColorVal
|
||||
import { useTheme } from '@/store/theme/hook'
|
||||
import { setSpText } from '@/utils/pixelRatio'
|
||||
import { useAnimateColor } from '@/utils/hooks/useAnimateColor'
|
||||
import { useAnimateNumber } from '@/utils/hooks/useAnimateNumber'
|
||||
import { DEFAULT_DURATION, useAnimateNumber } from '@/utils/hooks/useAnimateNumber'
|
||||
// import { AppColors } from '@/theme'
|
||||
|
||||
export interface TextProps extends _TextProps {
|
||||
@ -17,17 +17,50 @@ export interface TextProps extends _TextProps {
|
||||
color?: ColorValue
|
||||
}
|
||||
|
||||
// const warpText = <P extends TextProps>(Component: ComponentType<TextProps>) => {
|
||||
// return ({ style, size = 15, color, children, ...props }: P) => {
|
||||
// const theme = useTheme()
|
||||
// return (
|
||||
// <Component
|
||||
// style={StyleSheet.compose({ fontFamily: 'System', fontSize: setSpText(size), color: color ?? theme['c-font'] }, style)}
|
||||
// {...props}
|
||||
// >{children}</Component>
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
export default ({ style, size = 15, color, children, ...props }: TextProps) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Text
|
||||
style={StyleSheet.compose({ fontSize: setSpText(size), color: color ?? theme['c-font'] }, style)}
|
||||
style={StyleSheet.compose({ fontFamily: 'System', fontSize: setSpText(size), color: color ?? theme['c-font'] }, style)}
|
||||
{...props}
|
||||
>{children}</Text>
|
||||
)
|
||||
}
|
||||
|
||||
export interface AnimatedTextProps extends _AnimatedTextProps {
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
size?: number
|
||||
/**
|
||||
* 字体颜色
|
||||
*/
|
||||
color?: ColorValue
|
||||
}
|
||||
export const AnimatedText = ({ style, size = 15, color, children, ...props }: AnimatedTextProps) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Animated.Text
|
||||
style={StyleSheet.compose({ fontFamily: 'System', fontSize: setSpText(size), color: color ?? theme['c-font'] }, style as TextStyle)}
|
||||
{...props}
|
||||
>{children}</Animated.Text>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
type _AnimatedTextProps = ComponentProps<(typeof Animated)['Text']>
|
||||
export interface AnimatedColorTextProps extends _AnimatedTextProps {
|
||||
@ -48,7 +81,7 @@ export const AnimatedColorText = ({ style, size = 15, opacity: _opacity, color:
|
||||
const theme = useTheme()
|
||||
|
||||
const [color] = useAnimateColor(_color ?? theme['c-font'])
|
||||
const [opacity] = useAnimateNumber(_opacity ?? 1)
|
||||
const [opacity] = useAnimateNumber(_opacity ?? 1, DEFAULT_DURATION, false)
|
||||
|
||||
return (
|
||||
<Animated.Text
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react'
|
||||
import { forwardRef, memo, useImperativeHandle, useState } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { BorderWidths } from '@/theme'
|
||||
import ButtonBar from './ActionBar'
|
||||
@ -6,14 +6,31 @@ import { useNavigationComponentDidAppear } from '@/navigation'
|
||||
import { NAV_SHEAR_NATIVE_IDS } from '@/config/constant'
|
||||
import { scaleSizeW } from '@/utils/pixelRatio'
|
||||
import { useTheme } from '@/store/theme/hook'
|
||||
import Text from '@/components/common/Text'
|
||||
import Text, { AnimatedText } from '@/components/common/Text'
|
||||
import { createStyle } from '@/utils/tools'
|
||||
import StatusBar from '@/components/common/StatusBar'
|
||||
import Image from '@/components/common/Image'
|
||||
import { useListInfo } from './state'
|
||||
import { useAnimateOnecNumber } from '@/utils/hooks/useAnimateNumber'
|
||||
|
||||
const IMAGE_WIDTH = scaleSizeW(70)
|
||||
|
||||
const CountText = memo(({ count }: { count: string }) => {
|
||||
const [animFade] = useAnimateOnecNumber(0, 1, 250, false)
|
||||
const [animTranslateY] = useAnimateOnecNumber(10, 0, 250, false)
|
||||
return (
|
||||
<AnimatedText style={{
|
||||
...styles.playCount,
|
||||
opacity: animFade,
|
||||
transform: [
|
||||
{ translateY: animTranslateY },
|
||||
],
|
||||
}} numberOfLines={ 1 }>{count}</AnimatedText>
|
||||
)
|
||||
}, (prevProps, nextProps) => {
|
||||
return true
|
||||
})
|
||||
|
||||
const Pic = ({ componentId, playCount, imgUrl }: {
|
||||
componentId: string
|
||||
playCount: string
|
||||
@ -28,12 +45,10 @@ const Pic = ({ componentId, playCount, imgUrl }: {
|
||||
|
||||
return (
|
||||
<View style={{ ...styles.listItemImg, width: IMAGE_WIDTH, height: IMAGE_WIDTH }}>
|
||||
<Image nativeID={`${NAV_SHEAR_NATIVE_IDS.songlistDetail_pic}_to_${info.id}`} url={imgUrl} style={{ flex: 1, justifyContent: 'flex-end', borderRadius: 4 }} />
|
||||
{
|
||||
playCount && animated
|
||||
? <Text style={styles.playCount} numberOfLines={ 1 }>{playCount}</Text>
|
||||
: null
|
||||
}
|
||||
<Image nativeID={`${NAV_SHEAR_NATIVE_IDS.songlistDetail_pic}_to_${info.id}`} url={imgUrl} style={{ flex: 1, borderRadius: 4 }} />
|
||||
{
|
||||
playCount && animated ? <CountText count={playCount} /> : null
|
||||
}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -95,6 +110,7 @@ const styles = createStyle({
|
||||
// backgroundColor: '#eee',
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
overflow: 'hidden',
|
||||
// width: 70,
|
||||
// height: 70,
|
||||
// ...Platform.select({
|
||||
|
@ -2,9 +2,9 @@ import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Animated } from 'react-native'
|
||||
|
||||
|
||||
const ANIMATION_DURATION = 800
|
||||
export const DEFAULT_DURATION = 800
|
||||
|
||||
export const useAnimateNumber = (val: number) => {
|
||||
export const useAnimateNumber = (val: number, duration = DEFAULT_DURATION, useNativeDriver = true) => {
|
||||
const anim = useMemo(() => new Animated.Value(0), [val])
|
||||
const [finished, setFinished] = useState(true)
|
||||
const currentNumber = useRef(val)
|
||||
@ -19,8 +19,8 @@ export const useAnimateNumber = (val: number) => {
|
||||
setFinished(false)
|
||||
Animated.timing(anim, {
|
||||
toValue: 1,
|
||||
duration: ANIMATION_DURATION,
|
||||
useNativeDriver: false,
|
||||
duration,
|
||||
useNativeDriver,
|
||||
}).start((finished) => {
|
||||
if (!finished) return
|
||||
// currentNumber.current = nextNumber
|
||||
@ -33,3 +33,28 @@ export const useAnimateNumber = (val: number) => {
|
||||
|
||||
return [animNumber, finished] as const
|
||||
}
|
||||
|
||||
export const useAnimateOnecNumber = (val: number, toVal: number, duration = DEFAULT_DURATION, useNativeDriver = true) => {
|
||||
const anim = useMemo(() => new Animated.Value(0), [])
|
||||
const [finished, setFinished] = useState(true)
|
||||
|
||||
const animNumber = anim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [val, toVal],
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
setFinished(false)
|
||||
Animated.timing(anim, {
|
||||
toValue: 1,
|
||||
duration,
|
||||
useNativeDriver,
|
||||
}).start((finished) => {
|
||||
if (!finished) return
|
||||
// currentNumber.current = nextNumber
|
||||
setFinished(true)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return [animNumber, finished] as const
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user