打字机效果
文字逐字显现并带有闪烁光标,模拟打字机输入效果。
交互预览
动效定义与代码
{
"slug": "typewriter",
"name": "打字机效果",
"nameEn": "Typewriter",
"description": "文字逐字显现并带有闪烁光标,模拟打字机输入效果。",
"descriptionEn": "Text appears character by character with a blinking cursor, simulating typewriter input.",
"category": "text",
"tags": [
"text",
"typewriter",
"cursor",
"sequential"
],
"trigger": "on-mount",
"difficulty": "intermediate",
"duration": "3s",
"easing": "steps(var(--chars), end)",
"cssProperties": [
"width"
],
"isGPUAccelerated": false,
"previewBg": "dark",
"keywords": [
"typewriter",
"typing",
"text reveal",
"cursor blink",
"sequential text"
],
"useCases": [
"Hero headline animation",
"Terminal/code simulation",
"AI chat typing indicator",
"Portfolio intro text"
],
"relatedAnimations": [
"text-gradient-flow"
],
"recommendedStyles": [
"synthwave",
"dark-mode",
"editorial"
],
"codeSnippets": [
{
"label": "CSS Keyframes",
"language": "css",
"code": "@keyframes typewriter {\n from { width: 0; }\n to { width: 100%; }\n}\n\n.typewriter {\n overflow: hidden;\n white-space: nowrap;\n animation: typewriter 3s steps(var(--typewriter-chars, 20), end) both;\n}\n\n/* Usage: set --typewriter-chars to match text length\n <span class=\"typewriter\" style=\"--typewriter-chars: 13\">Hello, World!</span> */\n\n@media (prefers-reduced-motion: reduce) {\n .typewriter {\n animation: none;\n overflow: visible;\n width: auto;\n }\n}"
},
{
"label": "Tailwind CSS",
"language": "css",
"code": "@keyframes typewriter {\n from { width: 0; }\n to { width: 100%; }\n}\n\n@utility animate-typewriter {\n overflow: hidden;\n white-space: nowrap;\n animation: typewriter 3s steps(var(--typewriter-chars, 20), end) both;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .typewriter {\n animation: none;\n overflow: visible;\n width: auto;\n }\n}"
},
{
"label": "Framer Motion",
"language": "tsx",
"code": "import { motion } from \"framer-motion\";\n\n// Tip: show full text immediately for reduced motion\n// import { useReducedMotion } from \"framer-motion\";\n// const reduced = useReducedMotion();\n// if (reduced) return <span>{text}</span>;\n\nconst text = \"Hello, World!\";\n\n<motion.span>\n {text.split(\"\").map((char, i) => (\n <motion.span\n key={i}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ delay: i * 0.05, duration: 0 }}\n >\n {char}\n </motion.span>\n ))}\n</motion.span>"
}
]
}