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

边框描边

边框像被画笔描绘一样逐渐显现,从一角开始沿四边绘制完成。

悬停时600ms

交互预览

动效定义与代码

{
  "slug": "border-trace",
  "name": "边框描边",
  "nameEn": "Border Trace",
  "description": "边框像被画笔描绘一样逐渐显现,从一角开始沿四边绘制完成。",
  "descriptionEn": "Border draws itself progressively like a pen tracing the outline from one corner.",
  "category": "hover",
  "tags": [
    "border",
    "draw",
    "trace",
    "outline",
    "svg"
  ],
  "trigger": "on-hover",
  "difficulty": "advanced",
  "duration": "600ms",
  "easing": "ease-in-out",
  "cssProperties": [
    "stroke-dashoffset"
  ],
  "isGPUAccelerated": false,
  "previewBg": "light",
  "keywords": [
    "border",
    "draw",
    "trace",
    "outline",
    "stroke",
    "pen"
  ],
  "useCases": [
    "Button hover effect",
    "Card focus state",
    "Navigation link highlight",
    "Feature box reveal"
  ],
  "relatedAnimations": [
    "hover-glow",
    "flip-card"
  ],
  "recommendedStyles": [
    "minimalist-flat",
    "line-art",
    "neo-brutalist"
  ],
  "codeSnippets": [
    {
      "label": "CSS Keyframes",
      "language": "css",
      "code": "/* Approach 1: Gradient border with background-size animation */\n@keyframes border-trace {\n  0% {\n    background-size: 0 2px, 2px 0, 0 2px, 2px 0;\n  }\n  25% {\n    background-size: 100% 2px, 2px 0, 0 2px, 2px 0;\n  }\n  50% {\n    background-size: 100% 2px, 2px 100%, 0 2px, 2px 0;\n  }\n  75% {\n    background-size: 100% 2px, 2px 100%, 100% 2px, 2px 0;\n  }\n  100% {\n    background-size: 100% 2px, 2px 100%, 100% 2px, 2px 100%;\n  }\n}\n\n.border-trace {\n  position: relative;\n  background:\n    linear-gradient(currentColor, currentColor) top left / 0 2px no-repeat,\n    linear-gradient(currentColor, currentColor) top right / 2px 0 no-repeat,\n    linear-gradient(currentColor, currentColor) bottom right / 0 2px no-repeat,\n    linear-gradient(currentColor, currentColor) bottom left / 2px 0 no-repeat;\n  transition: background-size 600ms ease-in-out;\n}\n\n.border-trace:hover {\n  background-size: 100% 2px, 2px 100%, 100% 2px, 2px 100%;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .border-trace {\n    transition: none;\n    border: 2px solid currentColor;\n  }\n  .border-trace:hover {\n    background: none;\n  }\n}"
    },
    {
      "label": "Tailwind CSS",
      "language": "css",
      "code": "/* Add to your global CSS or Tailwind v4 theme */\n\n/* Approach 2: SVG stroke-dashoffset for precise control */\n@utility animate-border-trace {\n  & svg rect {\n    stroke-dasharray: 1000;\n    stroke-dashoffset: 1000;\n    transition: stroke-dashoffset 600ms ease-in-out;\n  }\n}\n\n/* Usage with SVG overlay:\n  <div class=\"relative animate-border-trace group\">\n    <svg class=\"absolute inset-0 w-full h-full pointer-events-none\">\n      <rect\n        x=\"1\" y=\"1\" rx=\"8\"\n        width=\"calc(100% - 2px)\" height=\"calc(100% - 2px)\"\n        fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\n        class=\"group-hover:[stroke-dashoffset:0]\"\n      />\n    </svg>\n    Content\n  </div>\n*/\n\n@media (prefers-reduced-motion: reduce) {\n  .border-trace svg rect {\n    transition: none;\n    stroke-dashoffset: 0;\n  }\n}"
    },
    {
      "label": "Framer Motion",
      "language": "tsx",
      "code": "import { motion } from \"framer-motion\";\n\n// Tip: respect user's motion preferences\n// import { useReducedMotion } from \"framer-motion\";\n// const reduced = useReducedMotion();\n// if (reduced) return <div style={{ border: \"2px solid\" }}>{children}</div>;\n\nfunction BorderTrace({ children }: { children: React.ReactNode }) {\n  const pathVariants = {\n    hidden: { pathLength: 0, opacity: 0 },\n    visible: { pathLength: 1, opacity: 1 },\n  };\n\n  return (\n    <div style={{ position: \"relative\", padding: \"1rem\" }}>\n      <svg\n        style={{ position: \"absolute\", inset: 0, width: \"100%\", height: \"100%\" }}\n      >\n        <motion.rect\n          x=\"1\" y=\"1\" rx=\"8\"\n          width=\"calc(100% - 2px)\"\n          height=\"calc(100% - 2px)\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth={2}\n          variants={pathVariants}\n          initial=\"hidden\"\n          whileHover=\"visible\"\n          transition={{ duration: 0.6, ease: \"easeInOut\" }}\n        />\n      </svg>\n      {children}\n    </div>\n  );\n}"
    }
  ]
}