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

Framer Motion交互式悬停按钮动画:文本截断问题

Framer Motion交互式悬停按钮文本截断问题

需求

  • 默认状态下显示idleText,背景为白色
  • 悬停时,通过clipPath动画隐藏白色背景,同时显示hoverText
  • 按钮宽度可平滑动画以适配不同文本长度

当前问题

idleText(例如"Instagram")被截断,仅显示部分文本(如"stagra")

代码实现

import { motion } from "motion/react";
import type { ComponentPropsWithRef } from "react";
import { useState } from "react";
import { clsx } from "clsx";

interface InteractiveHoverButtonProps extends ComponentPropsWithRef<"button"> {
  idleText: string;
  hoverText: string;
}

function InteractiveHoverButton({
  className,
  ref,
  idleText,
  hoverText,
}: InteractiveHoverButtonProps) {
  const [isHovered, setIsHovered] = useState(true);

  return (
    <motion.button
      className={clsx(
        "relative overflow-hidden bg-black border-2 border-gray-800 text-white font-semibold rounded-full cursor-pointer transition-all duration-300 ease-in-out h-[36px]",
        {
          "pl-7 pr-4": isHovered,
          "px-5": !isHovered,
        },
        className
      )}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
      transition={{
        duration: 0.3,
        ease: "easeInOut",
      }}
      ref={ref}
    >
      <motion.div
        className="relative z-10 flex items-center justify-center h-full overflow-hidden"
        animate={{
          width: isHovered ? "auto" : 0,
        }}
        transition={{
          duration: 0.3,
          ease: "easeInOut",
        }}
      >
        <span className="whitespace-nowrap text-sm text-white">
          {hoverText}
        </span>
      </motion.div>

      <motion.div
        className="absolute inset-0 bg-white rounded-full flex items-center justify-center"
        animate={{
          clipPath: isHovered
            ? "circle(6px at 20px 50%)"
            : "circle(100% at 50% 50%)",
        }}
        transition={{
          duration: 0.3,
          ease: "easeInOut",
        }}
      >
        <motion.span
          className="text-black font-semibold"
          animate={{
            opacity: isHovered ? 0 : 1,
          }}
          transition={{
            duration: 0.1,
            delay: isHovered ? 0 : 0.2,
          }}
        >
          {idleText}
        </motion.span>
      </motion.div>
    </motion.button>
  );
}

export { InteractiveHoverButton };

已尝试的解决方案

  • 固定内边距方案:使用统一的px-6内边距,但无法适配不同文本长度
  • 布局动画:使用Framer Motion的layout属性,但动画仍有跳变
  • 计算宽度:尝试根据文本长度计算宽度,但对不同字体不准确
  • 最小宽度方案:尝试min-w-fit、w-auto等多种组合

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 15:52:36