优化歌词详情页未激活状态歌词颜色

This commit is contained in:
lyswhut 2023-12-17 20:52:16 +08:00
parent fa879a8c4e
commit 811c6dc9fb
8 changed files with 64 additions and 15 deletions

View File

@ -3,6 +3,7 @@ import { Text, type TextProps as _TextProps, StyleSheet, Animated, type ColorVal
import { useTheme } from '@/store/theme/hook' import { useTheme } from '@/store/theme/hook'
import { setSpText } from '@/utils/pixelRatio' import { setSpText } from '@/utils/pixelRatio'
import { useAnimateColor } from '@/utils/hooks/useAnimateColor' import { useAnimateColor } from '@/utils/hooks/useAnimateColor'
import { useAnimateNumber } from '@/utils/hooks/useAnimateNumber'
// import { AppColors } from '@/theme' // import { AppColors } from '@/theme'
export interface TextProps extends _TextProps { export interface TextProps extends _TextProps {
@ -38,15 +39,20 @@ export interface AnimatedColorTextProps extends _AnimatedTextProps {
* *
*/ */
color?: string color?: string
/**
*
*/
opacity?: number
} }
export const AnimatedColorText = ({ style, size = 15, color: _color, children, ...props }: AnimatedColorTextProps) => { export const AnimatedColorText = ({ style, size = 15, opacity: _opacity, color: _color, children, ...props }: AnimatedColorTextProps) => {
const theme = useTheme() const theme = useTheme()
const [color] = useAnimateColor(_color ?? theme['c-font']) const [color] = useAnimateColor(_color ?? theme['c-font'])
const [opacity] = useAnimateNumber(_opacity ?? 1)
return ( return (
<Animated.Text <Animated.Text
style={StyleSheet.compose({ fontSize: setSpText(size), color: color as unknown as ColorValue }, style as TextStyle)} style={StyleSheet.compose({ fontSize: setSpText(size), color: color as unknown as ColorValue, opacity }, style as TextStyle)}
{...props} {...props}
>{children}</Animated.Text> >{children}</Animated.Text>
) )

View File

@ -25,6 +25,6 @@ export default memo(() => {
const styles = createStyle({ const styles = createStyle({
content: { content: {
marginTop: 5, marginTop: 5,
// marginBottom: 15, marginBottom: 15,
}, },
}) })

View File

@ -32,6 +32,6 @@ export default memo(() => {
const styles = createStyle({ const styles = createStyle({
content: { content: {
marginTop: 5, marginTop: 5,
marginBottom: 15, // marginBottom: 15,
}, },
}) })

View File

@ -12,8 +12,8 @@ export default memo(() => {
<> <>
<Theme /> <Theme />
<IsAutoTheme /> <IsAutoTheme />
<IsDynamicBg />
<IsHideBgDark /> <IsHideBgDark />
<IsDynamicBg />
</> </>
) )
}) })

View File

@ -35,10 +35,12 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
return active ? [ return active ? [
theme['c-primary'], theme['c-primary'],
theme['c-primary-alpha-200'], theme['c-primary-alpha-200'],
] : [ 1,
] as const : [
theme['c-350'], theme['c-350'],
theme['c-300'], theme['c-300'],
] 0.6,
] as const
}, [activeLine, lineNum, theme]) }, [activeLine, lineNum, theme])
const handleLayout = ({ nativeEvent }: LayoutChangeEvent) => { const handleLayout = ({ nativeEvent }: LayoutChangeEvent) => {
@ -53,14 +55,14 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
...styles.lineText, ...styles.lineText,
textAlign, textAlign,
lineHeight, lineHeight,
}} textBreakStrategy="simple" color={colors[0]} size={size}>{line.text}</AnimatedColorText> }} textBreakStrategy="simple" color={colors[0]} opacity={colors[2]} size={size}>{line.text}</AnimatedColorText>
{ {
line.extendedLyrics.map((lrc, index) => { line.extendedLyrics.map((lrc, index) => {
return (<AnimatedColorText style={{ return (<AnimatedColorText style={{
...styles.lineTranslationText, ...styles.lineTranslationText,
textAlign, textAlign,
lineHeight: lineHeight * 0.8, lineHeight: lineHeight * 0.8,
}} textBreakStrategy="simple" key={index} color={colors[1]} size={size * 0.8}>{lrc}</AnimatedColorText>) }} textBreakStrategy="simple" key={index} color={colors[1]} opacity={colors[2]} size={size * 0.8}>{lrc}</AnimatedColorText>)
}) })
} }
</View> </View>

View File

@ -74,10 +74,12 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
return active ? [ return active ? [
theme['c-primary'], theme['c-primary'],
theme['c-primary-alpha-200'], theme['c-primary-alpha-200'],
] : [ 1,
] as const : [
theme['c-350'], theme['c-350'],
theme['c-300'], theme['c-300'],
] 0.6,
] as const
}, [activeLine, lineNum, theme]) }, [activeLine, lineNum, theme])
const handleLayout = ({ nativeEvent }: LayoutChangeEvent) => { const handleLayout = ({ nativeEvent }: LayoutChangeEvent) => {
@ -93,14 +95,14 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
...styles.lineText, ...styles.lineText,
textAlign, textAlign,
lineHeight, lineHeight,
}} textBreakStrategy="simple" color={colors[0]} size={size}>{line.text}</AnimatedColorText> }} textBreakStrategy="simple" color={colors[0]} opacity={colors[2]} size={size}>{line.text}</AnimatedColorText>
{ {
line.extendedLyrics.map((lrc, index) => { line.extendedLyrics.map((lrc, index) => {
return (<AnimatedColorText style={{ return (<AnimatedColorText style={{
...styles.lineTranslationText, ...styles.lineTranslationText,
textAlign, textAlign,
lineHeight: lineHeight * 0.8, lineHeight: lineHeight * 0.8,
}} textBreakStrategy="simple" key={index} color={colors[1]} size={size * 0.8}>{lrc}</AnimatedColorText>) }} textBreakStrategy="simple" key={index} color={colors[1]} opacity={colors[2]} size={size * 0.8}>{lrc}</AnimatedColorText>)
}) })
} }
</View> </View>

View File

@ -21,10 +21,14 @@ export const useAnimateColor = (color: string) => {
toValue: 1, toValue: 1,
duration: ANIMATION_DURATION, duration: ANIMATION_DURATION,
useNativeDriver: false, useNativeDriver: false,
}).start(() => { }).start((finished) => {
currentColor.current = nextColor if (!finished) return
// currentColor.current = nextColor
setFinished(true) setFinished(true)
}) })
requestAnimationFrame(() => {
currentColor.current = nextColor
})
}, [nextColor]) }, [nextColor])
return [animColor, finished] as const return [animColor, finished] as const

View File

@ -0,0 +1,35 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import { Animated } from 'react-native'
const ANIMATION_DURATION = 800
export const useAnimateNumber = (val: number) => {
const anim = useMemo(() => new Animated.Value(0), [val])
const [finished, setFinished] = useState(true)
const currentNumber = useRef(val)
const nextNumber = useMemo(() => val, [val])
const animNumber = anim.interpolate({
inputRange: [0, 1],
outputRange: [currentNumber.current, nextNumber],
})
useEffect(() => {
setFinished(false)
Animated.timing(anim, {
toValue: 1,
duration: ANIMATION_DURATION,
useNativeDriver: false,
}).start((finished) => {
if (!finished) return
// currentNumber.current = nextNumber
setFinished(true)
})
requestAnimationFrame(() => {
currentNumber.current = nextNumber
})
}, [nextNumber])
return [animNumber, finished] as const
}