【翻译】用 Reanimated CSS 动画为 TextInput 添加发光效果

0 阅读2分钟

用 Reanimated CSS 动画为 TextInput 添加发光效果

文章头图

细微的 UI 反馈会让应用更有生命力。给文本输入框增加质感最简单的方法之一,就是在用户开始输入时触发一个发光效果。

借助 Reanimated 的 CSS 动画支持,你可以用很少几行代码做到这一点:不需要 useSharedValue,不需要 useAnimatedStyle,只用 keyframes 和 boxShadow

The Approach

思路很直接:

  1. 定义两个关键帧动画:一个让 boxShadow 渐显,一个让它渐隐。
const glowIn: CSSAnimationKeyframes = {
  from: { boxShadow: `0 0 0 0 ${GLOW_COLOR}00` },
  to: { boxShadow: `0 0 32px 4px ${GLOW_COLOR}80` },
};
 
const glowOut: CSSAnimationKeyframes = {
  from: { boxShadow: `0 0 32px 4px ${GLOW_COLOR}59` },
  to: { boxShadow: `0 0 0 0 ${GLOW_COLOR}00` },
};
  1. 根据输入框是否有文本,在两者之间切换。
const [text, setText] = useState("");
const hasText = text.length > 0;
 
return (
  <Animated.View
    style={{
      animationName: hasText ? glowIn : glowOut,
    }}
  />
);
  1. Animated.View 包住 TextInput,再通过样式属性以声明式方式应用动画。
import { useState } from "react";
import { StyleSheet, TextInput, View } from "react-native";
import Animated, { type CSSAnimationKeyframes } from "react-native-reanimated";
 
const GLOW_COLOR = "#6C63FF";
 
const glowIn: CSSAnimationKeyframes = {
  from: { boxShadow: `0 0 0 0 ${GLOW_COLOR}00` },
  to: { boxShadow: `0 0 32px 4px ${GLOW_COLOR}80` },
};
 
const glowOut: CSSAnimationKeyframes = {
  from: { boxShadow: `0 0 32px 4px ${GLOW_COLOR}59` },
  to: { boxShadow: `0 0 0 0 ${GLOW_COLOR}00` },
};
 
export function GlowInput() {
  const [text, setText] = useState("");
  const hasText = text.length > 0;
 
  return (
    <View style={styles.container}>
      <Animated.View
        style={[
          styles.glow,
          {
            animationName: hasText ? glowIn : glowOut,
            animationDuration: hasText ? "400ms" : "500ms",
            animationFillMode: "forwards",
            animationTimingFunction: "ease-out",
          },
        ]}
      >
        <TextInput
          autoFocus
          value={text}
          onChangeText={setText}
          placeholder="Type something..."
          placeholderTextColor="#999"
          cursorColor={GLOW_COLOR}
          style={styles.input}
        />
      </Animated.View>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    paddingHorizontal: 24,
  },
  glow: {
    borderRadius: 999,
  },
  input: {
    color: "#fff",
    fontSize: 18,
    fontWeight: "500",
    paddingHorizontal: 20,
    paddingVertical: 16,
    backgroundColor: "#1c1c1e",
    borderRadius: 999,
    borderWidth: 1,
    borderColor: "#333",
  },
});

Tips

  • 替换颜色:修改 GLOW_COLOR 来匹配你应用的强调色。错误态可以用红色,成功态可以用绿色,按你的场景来定。
  • 调节强度32px 的模糊半径和 4px 的扩散值决定了发光有多“戏剧化”。如果你想更克制一些,就把它们调小。
  • 改为在 focus 时触发:如果你希望用户点按输入框就发光,而不是输入后才发光,把 hasText 判断改成 onFocus / onBlur 状态即可。

Want to go deeper?

React Native 课程里有一节 Animations and Gestures,内容包括 Reanimated 辅助函数(withTimingwithSpring 及相关 API)和 React Native Gesture Handler 的手势类型,并配有一个小型示例应用可供参考。

Animations and Gestures 课程封面

课程:Animations and Gestures

完整课程目录可见 React Native course

如果你希望持续获取实用技巧、实验内容与更新,也可以订阅我的 newsletter

如果你想和我合作,可以通过 beto@codewithbeto.dev 联系我。