汉堡菜单转X形动画问题:transform-origin与关键帧动画异常
汉堡菜单转X形动画问题修复
问题描述
尝试实现汉堡菜单展开为X形的动画,但实际效果不符合预期,调整translate值与transform-origin后仍未解决。
原代码
HTML
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect class="top" y="8.5" width="48" height="3.875" fill="blue" /> <rect class="middle" y="22.0625" width="48" height="3.875" fill="blue" /> <rect class="bottom" y="35.625" width="48" height="3.875" fill="blue" /> </svg>
CSS
svg:hover .top { animation-name: top; animation-duration: 1.5s; animation-timing-function: ease-in-out; /*transform-origin: 25% 25%;*/ animation-fill-mode: forwards; } svg:hover .middle { animation-name: middle; animation-duration: 1.5s; animation-timing-function: linear; transform-origin: center center; animation-fill-mode: forwards; } svg:hover .bottom { animation-name: bottom; animation-duration: 1.5s; animation-timing-function: ease-in-out; /*transform-origin: 25% 25%;*/ animation-fill-mode: forwards; } @keyframes top { 0% { transform: translateY(0); } 50% { transform: translateY(30%); } 100% { transform: rotate(45deg) translateY(-25%); } } @keyframes middle { 50% { opacity: 0; } 100% { opacity: 0; } } @keyframes bottom { 0% { transform: translateY(0); } 50% { transform: translateY(-30%); } 100% { transform: rotate(-45deg); } }
问题分析
- transform顺序错误:CSS transform按从右到左的顺序生效,原代码先
rotate再translate,导致平移在旋转后的坐标系下执行,位置严重偏移。 - translate单位不合适:百分比平移基于元素自身尺寸,无法精准定位到svg中心,应该用固定像素值。
- 未设置正确的transform-origin:旋转时未指定合适的原点,导致线条旋转后偏离预期的交叉点。
修复后的代码
CSS
svg { cursor: pointer; } svg .top, svg .bottom { transform-origin: center center; /* 设置旋转原点为元素中心 */ } svg:hover .top { animation-name: top; animation-duration: 0.5s; animation-timing-function: ease-in-out; animation-fill-mode: forwards; } svg:hover .middle { animation-name: middle; animation-duration: 0.5s; animation-timing-function: linear; animation-fill-mode: forwards; } svg:hover .bottom { animation-name: bottom; animation-duration: 0.5s; animation-timing-function: ease-in-out; animation-fill-mode: forwards; } @keyframes top { 0% { transform: translateY(0); } 100% { /* 先平移到中间位置,再旋转,transform从右到左执行 */ transform: translateY(13.5625px) rotate(45deg); } } @keyframes middle { 100% { opacity: 0; transform: scaleX(0); /* 增加缩放消失效果,更贴近目标表现 */ } } @keyframes bottom { 0% { transform: translateY(0); } 100% { transform: translateY(-13.5625px) rotate(-45deg); } }
关键修复点
- 调整transform顺序:先执行
translateY将线条移动到svg中心位置,再执行rotate,确保旋转围绕中心交叉点进行。 - 使用固定像素平移:计算上下线条到中心的距离(
22.0625 - 8.5 = 13.5625px),精准定位到中间位置。 - 设置transform-origin:将旋转原点设为元素中心,保证旋转后线条交叉在svg中心。
- 优化动画时长:缩短动画时长至0.5s,让交互更流畅自然。
内容的提问来源于stack exchange,提问作者araki
相关产品推荐
相关产品推荐

