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

如何在ReactJS中实现GitHub官网风格的悬浮卡片动画?

React实现GitHub式悬浮卡片Blob动画效果

核心技术思路

  1. 鼠标位置追踪:在卡片元素上监听mousemove、mouseenter、mouseleave事件,计算鼠标相对于卡片容器的坐标偏移,转化为百分比值驱动动画。
  2. CSS变量联动:将鼠标位置的百分比值存入CSS变量,通过transform实现卡片的3D倾斜变形(rotateX/rotateY),同时控制Blob元素的位置偏移。
  3. Blob形状动态调整:用SVG的<path>或CSS clip-path定义Blob形状,通过鼠标位置动态修改路径参数实现跟随变形;也可使用圆角div配合缩放/位移模拟基础Blob效果。
  4. 平滑过渡:给卡片和Blob元素添加transition或使用动画库的弹簧物理效果,让动画更自然流畅。

原生React实现代码示例

以下是无依赖的基础实现,包含卡片变形和Blob跟随效果:

import { useState, useEffect, useRef } from 'react';

const HoverCard = ({ children }) => {
  const cardRef = useRef(null);
  const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
  const [isHovered, setIsHovered] = useState(false);

  const handleMouseMove = (e) => {
    if (!cardRef.current) return;
    const rect = cardRef.current.getBoundingClientRect();
    // 计算鼠标在卡片内的百分比位置(中心为原点)
    const x = ((e.clientX - rect.left) / rect.width - 0.5) * 100;
    const y = ((e.clientY - rect.top) / rect.height - 0.5) * 100;
    setMousePos({ x, y });
  };

  useEffect(() => {
    const card = cardRef.current;
    if (!card) return;

    card.addEventListener('mousemove', handleMouseMove);
    card.addEventListener('mouseenter', () => setIsHovered(true));
    card.addEventListener('mouseleave', () => {
      setIsHovered(false);
      setMousePos({ x: 0, y: 0 });
    });

    return () => {
      card.removeEventListener('mousemove', handleMouseMove);
      card.removeEventListener('mouseenter', () => setIsHovered(true));
      card.removeEventListener('mouseleave', () => setIsHovered(false));
    };
  }, []);

  return (
    <div
      ref={cardRef}
      className="hover-card"
      style={{
        '--mouse-x': `${mousePos.x}%`,
        '--mouse-y': `${mousePos.y}%`,
        '--hover': isHovered ? 1 : 0,
      }}
    >
      {/* Blob背景元素 */}
      <div className="card-blob" />
      {/* 卡片内容 */}
      <div className="card-content">{children}</div>
    </div>
  );
};

export default HoverCard;

对应的CSS样式:

.hover-card {
  position: relative;
  width: 300px;
  height: 200px;
  padding: 2rem;
  border-radius: 16px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
  transition: transform 0.2s ease;
  transform: perspective(1000px) rotateX(calc(var(--mouse-y, 0) * -0.5deg)) rotateY(calc(var(--mouse-x, 0) * 0.5deg));
}

.card-blob {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 150px;
  height: 150px;
  border-radius: 45% 55% 70% 30% / 40% 50% 50% 60%;
  background: #2ea44f;
  transform: translate(
    calc(var(--mouse-x, 0) * -0.3%),
    calc(var(--mouse-y, 0) * -0.3%)
  ) scale(calc(1 + var(--hover, 0) * 0.1));
  opacity: calc(0.3 + var(--hover, 0) * 0.2);
  transition: all 0.3s ease;
  z-index: 0;
}

.card-content {
  position: relative;
  z-index: 1;
}

推荐实用库

如果需要更复杂的动画效果或简化开发流程,可使用以下库:

  • Framer Motion:通过motion组件和useMotionValue轻松实现鼠标跟随的弹簧动画,支持自定义Blob路径的动态修改,API简洁易上手。
  • React Spring:基于物理弹簧的动画库,适合模拟自然的跟随和变形效果,能精准控制动画的阻尼、刚度等参数。
  • GSAP:功能强大的动画引擎,可处理复杂的SVG路径变形和3D变换,适合对动画精度要求极高的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:37:33