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

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

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

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

The Approach

思路很直接:

  1. 定义两个关键帧动画:一个让 boxShadow 渐显,一个让它渐隐。
ts 复制代码
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. 根据输入框是否有文本,在两者之间切换。
ts 复制代码
const [text, setText] = useState("");
const hasText = text.length > 0;
 
return (
  <Animated.View
    style={{
      animationName: hasText ? glowIn : glowOut,
    }}
  />
);
  1. 用 Animated.View 包住 TextInput,再通过样式属性以声明式方式应用动画。
ts 复制代码
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 辅助函数(withTiming、withSpring 及相关 API)和 React Native Gesture Handler 的手势类型,并配有一个小型示例应用可供参考。

课程:Animations and Gestures

完整课程目录可见 React Native course。

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

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

相关推荐
恋猫de小郭11 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter
严肃小白兔11 小时前
TanStack Router 更新构建工具链:Node.js 兼容性、路由分割与前端工程实践
前端·node.js·状态模式
IT_陈寒11 小时前
Vue这个奇葩的响应式问题让我加班到凌晨
前端·人工智能·后端
风骏时光牛马12 小时前
功能可用性自动化测试验证
前端
LucianaiB1 天前
【元宝搜索开发者征文大赛】AI时代,学得慢就不用学?用元宝搜索打造一个教程保质期,确保每一个教程符合你的现状
前端·人工智能·ai编程
excel1 天前
JavaScript 对象池:减少高频对象创建与 GC 压力
前端
陈随易1 天前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
子兮曰1 天前
Chrome 权限元素实战:144 与 151 的渐进增强写法
前端·javascript·chrome
IT_陈寒1 天前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
强尼银手1 天前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript