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

React中使用useScroll与useTransform实现滚动文字渐填效果遇阻

解决React滚动时文字从上到下填充颜色的问题

你的思路没问题,但clip-path不生效的核心原因是:framer-motion的MotionValue不能直接拼接到字符串里当作普通数值使用,直接写${y}%会把y这个MotionValue对象转成无效字符串(比如[object Object]%),导致clip-path属性完全失效,所以文字始终全显示。

下面给你两种可行的修正方案:

方案一:直接生成完整的clip-path字符串

用useTransform直接生成对应滚动状态的完整clip-path值,让framer-motion自动处理插值过渡:

import { motion, useScroll, useTransform } from "framer-motion";

function ScrollFillText() {
  const { scrollY } = useScroll();
  // 滚动从0到500px时,clip-path从完全隐藏(高度0%)到完全显示(高度100%)
  const clipPath = useTransform(scrollY, [0, 500], [
    "polygon(0 0, 100% 0, 100% 0%, 0 0%)",
    "polygon(0 0, 100% 0, 100% 100%, 0 100%)"
  ]);

  return (
    <div className="textbox2" style={{ position: "relative" }}>
      {/* 下层:仅描边的文字 */}
      <h2 
        id="name" 
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          margin: 0,
          WebkitTextStroke: "1px #fff", // 描边样式
          color: "transparent" // 文字填充透明
        }}
      >
        MAKS
      </h2>
      {/* 上层:带填充的文字,用clipPath控制显示范围 */}
      <motion.h2 
        id="overname" 
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          margin: 0,
          clipPath
        }}
      >
        MAKS
      </motion.h2>
    </div>
  );
}

export default ScrollFillText;

方案二:用数值型MotionValue拼接clip-path

如果坚持用数值变量y,需要确保在motion组件的style中使用模板字符串,因为只有motion组件能识别并动态更新MotionValue:

import { motion, useScroll, useTransform } from "framer-motion";

function ScrollFillText() {
  const { scrollY } = useScroll();
  const y = useTransform(scrollY, [0, 500], [0, 100]);

  return (
    <div className="textbox2" style={{ position: "relative" }}>
      <h2 
        id="name" 
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          margin: 0,
          WebkitTextStroke: "1px #fff",
          color: "transparent"
        }}
      >
        MAKS
      </h2>
      <motion.h2 
        id="overname" 
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          margin: 0,
          // 仅在motion组件的style中,这样的拼接才会被framer-motion解析
          clipPath: `polygon(0 0, 100% 0, 100% ${y}%, 0 ${y}%)`
        }}
      >
        MAKS
      </motion.h2>
    </div>
  );
}

export default ScrollFillText;

关键注意点

  1. 定位必须正确:父容器textbox2要设置position: relative,两个h2设置position: absolute和相同的top/left,确保它们完全重叠。
  2. 仅motion组件支持MotionValue:普通React元素的style无法解析MotionValue,所以控制clip-path的必须是motion.h2而非原生h2。
  3. 描边样式的兼容性:WebkitTextStroke是webkit内核的属性,若要兼容其他浏览器,可添加前缀或用SVG实现描边。

内容的提问来源于stack exchange,提问作者maksderylo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:20:10