本页出处
设计风格资料库
内容来自 luckymaomi 的 UI 风格库(复刻版),以 MIT 许可 提供。本站镜像收录,仅作学习参考;这一页的原始地址是 原站页面。
← 回到导览访问原站仓库
返回动效库
文字进阶

文字揭示

文字通过遮罩从下方逐行揭示显现,常用于英雄区标题和关键文案的戏剧性入场。

滚动时800ms

交互预览

动效定义与代码

{
  "slug": "text-reveal",
  "name": "文字揭示",
  "nameEn": "Text Reveal",
  "description": "文字通过遮罩从下方逐行揭示显现,常用于英雄区标题和关键文案的戏剧性入场。",
  "descriptionEn": "Text reveals line by line from behind a mask, creating a dramatic entrance for hero titles and key copy.",
  "category": "text",
  "tags": [
    "text",
    "reveal",
    "mask",
    "clip",
    "scroll"
  ],
  "trigger": "on-scroll",
  "difficulty": "intermediate",
  "duration": "800ms",
  "easing": "cubic-bezier(0.16, 1, 0.3, 1)",
  "cssProperties": [
    "clip-path",
    "transform",
    "opacity"
  ],
  "isGPUAccelerated": true,
  "previewBg": "dark",
  "keywords": [
    "text reveal",
    "mask",
    "clip path",
    "hero text",
    "headline animation",
    "scroll text"
  ],
  "useCases": [
    "Hero section headline entrance",
    "Landing page key messaging",
    "Section title scroll reveal",
    "Award-winning editorial layouts"
  ],
  "relatedAnimations": [
    "typewriter",
    "text-gradient-flow",
    "scroll-reveal"
  ],
  "recommendedStyles": [
    "editorial",
    "minimalist-flat",
    "dark-mode"
  ],
  "codeSnippets": [
    {
      "label": "CSS Keyframes",
      "language": "css",
      "code": "@keyframes text-reveal {\n  from {\n    clip-path: inset(100% 0 0 0);\n    transform: translateY(12px);\n    opacity: 0;\n  }\n  to {\n    clip-path: inset(0 0 0 0);\n    transform: translateY(0);\n    opacity: 1;\n  }\n}\n\n.text-reveal {\n  --sk-duration: 800ms;\n  --sk-delay: 0ms;\n  --sk-ease: cubic-bezier(0.16, 1, 0.3, 1);\n  animation: text-reveal var(--sk-duration) var(--sk-ease) var(--sk-delay) both;\n}\n\n/* Stagger each line */\n.text-reveal:nth-child(2) { --sk-delay: 120ms; }\n.text-reveal:nth-child(3) { --sk-delay: 240ms; }\n\n@media (prefers-reduced-motion: reduce) {\n  .text-reveal {\n    animation: none;\n    clip-path: none;\n    opacity: 1;\n    transform: none;\n  }\n}"
    },
    {
      "label": "Tailwind CSS",
      "language": "css",
      "code": "@keyframes text-reveal {\n  from {\n    clip-path: inset(100% 0 0 0);\n    transform: translateY(12px);\n    opacity: 0;\n  }\n  to {\n    clip-path: inset(0 0 0 0);\n    transform: translateY(0);\n    opacity: 1;\n  }\n}\n\n@utility animate-text-reveal {\n  --sk-duration: 800ms;\n  --sk-delay: 0ms;\n  --sk-ease: cubic-bezier(0.16, 1, 0.3, 1);\n  animation: text-reveal var(--sk-duration) var(--sk-ease) var(--sk-delay) both;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .text-reveal {\n    animation: none;\n    clip-path: none;\n    opacity: 1;\n    transform: none;\n  }\n}"
    },
    {
      "label": "Framer Motion",
      "language": "tsx",
      "code": "import { motion } from \"framer-motion\";\n\nconst lineVariants = {\n  hidden: {\n    clipPath: \"inset(100% 0 0 0)\",\n    y: 12,\n    opacity: 0,\n  },\n  visible: (i: number) => ({\n    clipPath: \"inset(0 0 0 0)\",\n    y: 0,\n    opacity: 1,\n    transition: {\n      duration: 0.8,\n      delay: i * 0.12,\n      ease: [0.16, 1, 0.3, 1],\n    },\n  }),\n};\n\n{lines.map((line, i) => (\n  <motion.span\n    key={i}\n    custom={i}\n    variants={lineVariants}\n    initial=\"hidden\"\n    whileInView=\"visible\"\n    viewport={{ once: true }}\n    className=\"block\"\n  >\n    {line}\n  </motion.span>\n))}"
    }
  ]
}