You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将使用easeInExpo缓动的jQuery菜单代码重写为原生JS+CSS实现

实现方案

方案1:CSS Transition + 极简JS(生产环境移动端首选)

该方案依赖CSS硬件加速,动画流畅度远高于纯JS实现,完全匹配原代码的交互逻辑,是移动端场景的最优选择:

  • 缓动效果:原代码的easeInExpo可以用CSS cubic-bezier(0.95, 0.05, 0.795, 0.035) 1:1还原
  • 滑动效果通过max-height实现,解决height: auto无法触发过渡的问题
  • 延迟、时长参数完全对齐原代码:展开延迟35ms、时长300ms,收起时长550ms

CSS代码

ul#nav {
  max-height: 0;
  overflow: hidden;
  /* 收起动画:时长550ms,默认缓动和原jQuery slideUp效果一致 */
  transition: max-height 550ms ease;
  /* 移动端性能优化 */
  will-change: max-height;
}
ul#nav.active {
  /* 取值要大于导航菜单最大可能高度,比如导航最高200px可设为300px */
  max-height: 300px;
  /* 展开动画:延迟35ms,时长300ms,easeInExpo缓动 */
  transition: max-height 300ms cubic-bezier(0.95, 0.05, 0.795, 0.035) 35ms;
}
button#hmenu.active {
  /* 保留原有按钮激活样式即可 */
}

JS代码

const hmenu = document.querySelector('button#hmenu');
const nav = document.querySelector('ul#nav');

hmenu.addEventListener('click', () => {
  const isActive = hmenu.classList.contains('active');
  if (!isActive) {
    nav.classList.add('active');
    hmenu.classList.add('active');
  } else {
    nav.classList.remove('active');
    hmenu.classList.remove('active');
  }
});

方案2:纯JS原生动画实现(精细控制场景备选)

如果需要更灵活的动画控制(比如中途打断动画、动态高度适配),可以用requestAnimationFrame实现,直接复用原有的缓动函数:

const hmenu = document.querySelector('button#hmenu');
const nav = document.querySelector('ul#nav');
let isNavOpen = false;
let animationId = null;

// 复用原easeInExpo缓动函数
function easeInExpo(t, b, c, d) {
  return t == 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
}

// 滑动展开函数
function slideDown(el, duration = 300, delay = 35) {
  setTimeout(() => {
    const startHeight = 0;
    el.style.overflow = 'hidden';
    // 获取元素真实高度
    el.style.maxHeight = 'none';
    const targetHeight = el.offsetHeight;
    el.style.height = startHeight + 'px';
    const startTime = performance.now();
    
    function animate(now) {
      const elapsed = now - startTime;
      const progress = Math.min(elapsed / duration, 1);
      const currentHeight = easeInExpo(progress, startHeight, targetHeight - startHeight, 1);
      el.style.height = currentHeight + 'px';
      if (progress < 1) {
        animationId = requestAnimationFrame(animate);
      } else {
        el.style.height = 'auto';
      }
    }
    if (animationId) cancelAnimationFrame(animationId);
    animationId = requestAnimationFrame(animate);
  }, delay);
}

// 滑动收起函数
function slideUp(el, duration = 550) {
  const startHeight = el.offsetHeight;
  el.style.overflow = 'hidden';
  const startTime = performance.now();
  
  function animate(now) {
    const elapsed = now - startTime;
    const progress = Math.min(elapsed / duration, 1);
    const currentHeight = startHeight - (progress * startHeight);
    el.style.height = currentHeight + 'px';
    if (progress < 1) {
      animationId = requestAnimationFrame(animate);
    } else {
      el.style.height = '0';
    }
  }
  if (animationId) cancelAnimationFrame(animationId);
  animationId = requestAnimationFrame(animate);
}

// 绑定点击事件
hmenu.addEventListener('click', () => {
  if (!isNavOpen) {
    slideDown(nav);
    hmenu.classList.add('active');
    isNavOpen = true;
  } else {
    slideUp(nav);
    hmenu.classList.remove('active');
    isNavOpen = false;
  }
});

生产环境注意事项

  • 方案1中max-height不要设置过大,否则会出现动画收尾过快的问题,建议比实际最大导航高度高30%即可
  • 移动端可添加touch-action: manipulation到按钮上,避免点击300ms延迟
  • 方案1兼容性覆盖iOS9+、安卓4.4+,完全满足绝大多数移动端生产场景需求

内容的提问来源于stack exchange,提问作者drooh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 17:18:01