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

基于HTML、CSS和JavaScript实现任天堂Wii菜单缩放过渡动画

实现任天堂Wii菜单频道点击过渡动画方案

核心逻辑拆解

原版动画的关键不是放大频道组件,而是通过视口聚焦过渡营造镜头推进的错觉:点击频道时,一个与频道完全匹配的“窗口”从当前位置平滑放大至全屏,同时内部内容切换为频道页面,频道本身全程保持原尺寸无变形。

原生实现步骤(HTML/CSS/JS)

1. 基础布局结构

<!-- 主菜单容器 -->
<div class="wii-menu">
  <div class="channel" data-channel="1">频道1</div>
  <div class="channel" data-channel="2">频道2</div>
  <!-- 更多频道 -->
</div>

<!-- 过渡遮罩层 -->
<div class="transition-overlay">
  <div class="overlay-content">
    <!-- 频道内容容器,默认隐藏 -->
    <div class="channel-content" id="content-1">频道1内容</div>
    <div class="channel-content" id="content-2">频道2内容</div>
  </div>
</div>

2. CSS样式与动画

.wii-menu {
  position: relative;
  width: 100vw;
  height: 100vh;
  background: #000;
}

.channel {
  position: absolute;
  width: 180px;
  height: 240px;
  background: #333;
  color: #fff;
  /* 频道定位,示例值 */
  top: 100px;
  left: 200px;
  cursor: pointer;
}

.transition-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  overflow: hidden;
  z-index: 999;
  background: #000;
  /* 初始隐藏 */
  opacity: 0;
}

.channel-content {
  display: none;
  width: 100vw;
  height: 100vh;
  color: #fff;
}

/* 放大动画关键帧 */
@keyframes zoomToFull {
  from {
    /* 初始尺寸和位置由JS动态设置 */
  }
  to {
    width: 100vw;
    height: 100vh;
    top: 0;
    left: 0;
    opacity: 1;
  }
}

.overlay-active {
  animation: zoomToFull 350ms ease-out forwards;
}

3. JS触发与控制

const channels = document.querySelectorAll('.channel');
const overlay = document.querySelector('.transition-overlay');
const contents = document.querySelectorAll('.channel-content');

channels.forEach(channel => {
  channel.addEventListener('click', () => {
    const rect = channel.getBoundingClientRect();
    // 设置遮罩层初始位置和尺寸
    overlay.style.width = `${rect.width}px`;
    overlay.style.height = `${rect.height}px`;
    overlay.style.top = `${rect.top}px`;
    overlay.style.left = `${rect.left}px`;
    overlay.style.opacity = '1';
    
    // 显示对应频道内容
    const channelId = channel.dataset.channel;
    contents.forEach(c => c.style.display = 'none');
    document.getElementById(`content-${channelId}`).style.display = 'block';
    
    // 触发动画
    overlay.classList.add('overlay-active');
    
    // 动画结束后隐藏菜单
    overlay.addEventListener('animationend', () => {
      document.querySelector('.wii-menu').style.display = 'none';
    }, { once: true });
  });
});

// 返回菜单逻辑(示例:点击内容区域返回)
contents.forEach(content => {
  content.addEventListener('click', () => {
    document.querySelector('.wii-menu').style.display = 'block';
    overlay.classList.remove('overlay-active');
    // 重置遮罩层状态
    setTimeout(() => {
      overlay.style.width = '0';
      overlay.style.height = '0';
      overlay.style.opacity = '0';
    }, 350);
  });
});

优化要点

  • 确保遮罩层初始的背景图与频道缩略图完全一致,避免视觉断层。
  • 使用getBoundingClientRect()获取精准的频道位置,避免偏移。
  • 动画时长设为300-400ms,匹配原版Wii的过渡节奏。
  • 可添加背景变暗的同步动画,增强沉浸感。

工具简化方案

如果不想手动计算参数,可使用GSAP动画库的fromTo方法,快速实现精准的尺寸和位置过渡,减少代码量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:03:14