如何实现弹出菜单箭头在hover与点击时的平滑左右切换
解决方案
问题分析
点击时箭头跳动的核心原因:
- hover状态的
transform: rotate(180deg)与点击后设置的transform: none产生冲突,触发不必要的过渡动画 - 切换图标类(
bi-chevron-left/bi-chevron-right)时,CSS过渡效果仍在生效,导致图标切换过程中出现旋转跳动
代码修改
1. 更新CSS
添加禁用过渡的工具类,同时调整hover和菜单激活状态的样式优先级:
#daily-muster-statuses-menu { opacity: 0; visibility: hidden; /* 给菜单添加过渡,优化显示/隐藏流畅度 */ transition: opacity 0.1s linear, visibility 0.1s linear; } #daily-muster-statuses:hover > #daily-muster-statuses-menu, #daily-muster-statuses-menu.show { opacity: 1; visibility: visible; } .dd-icon { bottom: 2.5px; left: 12px; opacity: 1; transition: transform 0.1s linear; } /* 仅菜单未激活时,hover触发箭头旋转 */ .outer-menu-item:not(.menu-active):hover .dd-icon { transform: rotate(180deg); } /* 临时禁用过渡的工具类 */ .dd-icon.no-transition { transition: none !important; } /* 菜单激活时,强制箭头保持指向右侧,覆盖hover效果 */ .menu-active .dd-icon { transform: none !important; }
2. 修改JavaScript
在切换图标时临时禁用过渡,同时给触发元素添加状态类控制hover效果:
const musterStatusesRollup = $('#daily-muster-statuses-rollup'); const musterStatusesMenu = $('#daily-muster-statuses-menu'); const musterStatusesChevron = musterStatusesRollup.find('.dd-icon'); const outerMenuItem = musterStatusesRollup.find('.outer-menu-item'); let menuIsShown = false; const hideDailyMusterStatusesMenu = () => { // 临时禁用过渡,切换图标类 musterStatusesChevron.addClass('no-transition'); musterStatusesChevron.removeClass('bi-chevron-right').addClass('bi-chevron-left'); // 强制浏览器重绘后恢复过渡 void musterStatusesChevron[0].offsetWidth; musterStatusesChevron.removeClass('no-transition'); musterStatusesMenu.removeClass('show'); outerMenuItem.removeClass('menu-active'); return (menuIsShown = false); }; const initialiseDailyMusterStatusesMenu = () => { musterStatusesRollup.on('click', e => { e.stopPropagation(); if (menuIsShown) { return hideDailyMusterStatusesMenu(); } // 临时禁用过渡,切换图标类 musterStatusesChevron.addClass('no-transition'); musterStatusesChevron.removeClass('bi-chevron-left').addClass('bi-chevron-right'); void musterStatusesChevron[0].offsetWidth; musterStatusesChevron.removeClass('no-transition'); musterStatusesMenu.addClass('show'); outerMenuItem.addClass('menu-active'); menuIsShown = true; $(document).one('click', hideDailyMusterStatusesMenu); }); };
关键说明
- 使用
no-transition类在图标切换瞬间禁用过渡,通过void element.offsetWidth强制浏览器重绘,避免过渡动画干扰图标切换 - 添加
menu-active类到触发元素,控制hover效果仅在菜单未激活时生效,解决hover与点击状态的样式冲突 - 统一菜单显示/隐藏的触发条件,同时给菜单添加过渡效果,提升交互流畅度
内容的提问来源于stack exchange,提问作者Kenny83
相关产品推荐
相关产品推荐

