如何修复Vue.js+TailwindCSS汉堡菜单转X形时底部线条对齐问题
修复Vue + TailwindCSS汉堡菜单X形对齐问题
问题描述
使用Vue.js和TailwindCSS开发汉堡菜单图标,需求是点击后三条线条转换为X形:
- 菜单打开时:顶部线条旋转45度并下移,中间线条渐隐,底部线条旋转-45度并上移
- 菜单关闭时:所有线条恢复汉堡样式
当前遇到的问题:底部线条转换为X形时错位,无法与顶部线条组成正确的X,调整translate属性后仍未解决。
原代码:
<template> <div class="md:hidden mr-6 mt-3"> <button @click="toggleMenu" class="text-gray-700 focus:outline-none"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="relative"> <path :class="menuOpen ? 'rotate-45 translate-x-1' : 'rotate-0'" d="M2 6C2 5.44772 2.44772 5 3 5H21C21.5523 5 22 5.44772 22 6C22 6.55228 21.5523 7 21 7H3C2.44772 7 2 6.55228 2 6Z" fill="currentColor"/> <path :class="menuOpen ? 'opacity-0' : 'opacity-100'" d="M2 12.0322C2 11.4799 2.44772 11.0322 3 11.0322H21C21.5523 11.0322 22 11.4799 22 12.0322C22 12.5845 21.5523 13.0322 21 13.0322H3C2.44772 13.0322 2 12.5845 2 12.0322Z" fill="currentColor"/> <path :class="menuOpen ? '-rotate-45 -translate-x-1' : 'rotate-0'" d="M3 17.0645C2.44772 17.0645 2 17.5122 2 18.0645C2 18.6167 2.44772 19.0645 3 19.0645H21C21.5523 19.0645 22 18.6167 22 18.0645C22 17.5122 21.5523 17.0645 21 17.0645H3Z" fill="currentColor"/> </svg> </button> </div> </template> <script setup> import { ref } from 'vue'; const menuOpen = ref(false); const toggleMenu = () => { menuOpen.value = menuOpen.value; } </script>
修复思路与解决方案
核心问题原因
- SVG元素默认变换原点为左上角,旋转时会导致线条偏移,无法围绕中心对齐。
- 原代码中位移方向错误(用了水平translate而非垂直),且toggle函数逻辑错误(未切换menuOpen状态)。
具体修复步骤
- 设置变换原点:给每个path添加
origin-center类,让旋转围绕线条自身中心进行。 - 修正位移方向:
- 顶部线条:旋转45度的同时,垂直向下平移
translate-y-3,使其移动到SVG中心位置。 - 底部线条:旋转-45度的同时,垂直向上平移
-translate-y-3,同样对齐到SVG中心。
- 顶部线条:旋转45度的同时,垂直向下平移
- 修复toggle函数:将
menuOpen.value = menuOpen.value改为menuOpen.value = !menuOpen.value,实现状态切换。 - 添加过渡动画:给path添加
transition-all duration-300类,让变换过程更平滑。
修改后的完整代码
<template> <div class="md:hidden mr-6 mt-3"> <button @click="toggleMenu" class="text-gray-700 focus:outline-none"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <!-- 顶部线条 --> <path :class="menuOpen ? 'rotate-45 translate-y-3 origin-center' : 'rotate-0 origin-center'" class="transition-all duration-300" d="M2 6C2 5.44772 2.44772 5 3 5H21C21.5523 5 22 5.44772 22 6C22 6.55228 21.5523 7 21 7H3C2.44772 7 2 6.55228 2 6Z" fill="currentColor" /> <!-- 中间线条 --> <path :class="menuOpen ? 'opacity-0' : 'opacity-100'" class="transition-all duration-300" d="M2 12.0322C2 11.4799 2.44772 11.0322 3 11.0322H21C21.5523 11.0322 22 11.4799 22 12.0322C22 12.5845 21.5523 13.0322 21 13.0322H3C2.44772 13.0322 2 12.5845 2 12.0322Z" fill="currentColor" /> <!-- 底部线条 --> <path :class="menuOpen ? '-rotate-45 -translate-y-3 origin-center' : 'rotate-0 origin-center'" class="transition-all duration-300" d="M3 17.0645C2.44772 17.0645 2 17.5122 2 18.0645C2 18.6167 2.44772 19.0645 3 19.0645H21C21.5523 19.0645 22 18.6167 22 18.0645C22 17.5122 21.5523 17.0645 21 17.0645H3Z" fill="currentColor" /> </svg> </button> </div> </template> <script setup> import { ref } from 'vue'; const menuOpen = ref(false); const toggleMenu = () => { menuOpen.value = !menuOpen.value; }; </script>
内容的提问来源于stack exchange,提问作者Haru_Tsubasa
相关产品推荐
相关产品推荐

