You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中用Framer Motion动态修改CSS Filter属性

解决方案

问题核心

你的问题根源有两点:

  • 普通Image组件(推测是Next.js Image)无法识别Framer Motion的MotionValue(即你定义的indicator),直接在它的style中设置filter不会生效。
  • 未将Image转换为支持Motion动画的组件,导致动态样式无法被解析渲染。

具体修复步骤

  1. 将Image转为Motion组件
    Framer Motion支持直接包装React组件,把普通Image变成支持动画的版本:

    const MotionImage = motion(Image);
    

    之后用<MotionImage>替代原<Image>,它就能处理动态的MotionValue了。

  2. 修正窗口高度获取逻辑
    直接用window.innerHeight会导致组件初始化时可能获取错误值,且窗口大小变化时不会更新。推荐用Framer Motion内置的useWindowSize钩子,或者自定义监听:

    // 方式1:Framer Motion内置钩子(需确保版本支持)
    const { height: windowHeight } = useWindowSize();
    
    // 方式2:自定义窗口大小监听
    const [windowHeight, setWindowHeight] = useState(window.innerHeight);
    useEffect(() => {
      const updateHeight = () => setWindowHeight(window.innerHeight);
      window.addEventListener('resize', updateHeight);
      return () => window.removeEventListener('resize', updateHeight);
    }, []);
    
  3. 正确绑定动态filter样式
    现在MotionImage是motion组件,可直接把indicator传入style的filter中,Framer Motion会自动处理动态值的实时更新。

修改后的完整代码

import { motion, useScroll, useTransform, useWindowSize } from "framer-motion";
import Image from "next/image"; // 假设使用Next.js Image

const HeroImage = "/path/to/your/image.jpg"; // 替换为你的图片路径

const heroImage = () => {
  const { height: windowHeight } = useWindowSize();
  const { scrollY } = useScroll();
  
  // 滚动从0到窗口高度时,饱和度从100%降至20%
  const saturation = useTransform(scrollY, [0, windowHeight], ["100%", "20%"]);

  const MotionImage = motion(Image);

  return (
    <motion.div className="fixed w-full bottom-0 z-0">
      <MotionImage
        className="hero-image"
        src={HeroImage}
        alt="Picture of me"
        style={{
          width: "100%",
          height: "auto",
          filter: `saturate(${saturation}) brightness(20%)`
        }}
        // Next.js Image必填属性,根据布局调整
        fill
        objectFit="cover"
      />
    </motion.div>
  );
};

export default heroImage;

额外注意事项

  • 若使用普通<img>标签,直接用<motion.img>即可,无需额外包装。
  • 若页面滚动高度小于窗口高度,动画可能无法完全触发,可调整useTransform的第二个参数(比如改成[0, document.body.scrollHeight])。
  • 检查CSS优先级:如果.hero-image类有其他filter样式,可能会覆盖动态值,可给动态filter加!important或调整类优先级。

内容的提问来源于stack exchange,提问作者Migel S. Sugiarto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:20:13