打开/关闭菜单
26
6679
46
1.2万
OGAS数据中枢
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

Widget:GameSwitcher:修订间差异

来自OGAS数据中枢
弃权者留言 | 贡献
无编辑摘要
弃权者留言 | 贡献
无编辑摘要
第47行: 第47行:
   }
   }


  /* 滑动指示器:根据当前active tab的位置和宽度移动 */
   function moveIndicator( tab ) {
   function moveIndicator( tab ) {
     var indicator = document.getElementById( 'gf-tab-indicator' );
     var indicator = document.getElementById( 'gf-tab-indicator' );
     var switcher = document.getElementById( 'gf-switcher' );
     var switcher = document.getElementById( 'gf-switcher' );
     if ( !indicator || !switcher ) { return; }
     if ( !indicator || !switcher ) { return; }
     var switcherRect = switcher.getBoundingClientRect();
     var sr = switcher.getBoundingClientRect();
     var tabRect = tab.getBoundingClientRect();
     var tr = tab.getBoundingClientRect();
     indicator.style.width = tabRect.width + 'px';
     indicator.style.width     = tr.width + 'px';
     indicator.style.transform = 'translateX(' + ( tabRect.left - switcherRect.left ) + 'px)';
     indicator.style.transform = 'translateX(' + ( tr.left - sr.left ) + 'px)';
   }
   }


   var currentGame = 'gf';
   var currentGame = 'gf';
   var switching = false;
   var switching   = false;
 
   var pending    = null; /* { game, tabEl } */
   function switchGame( game, tabEl ) {
    if ( game === currentGame || switching ) { return; }
    switching = true;


  function doSwitch( game, tabEl ) {
     var slides = document.querySelectorAll( '#gf-homepage .gf-hero-slide' );
     var slides = document.querySelectorAll( '#gf-homepage .gf-hero-slide' );
     var panels = document.querySelectorAll( '#gf-homepage .gf-content-panel' );
     var panels = document.querySelectorAll( '#gf-homepage .gf-content-panel' );
第72行: 第69行:
     var inSlide  = document.getElementById( 'hero-' + game );
     var inSlide  = document.getElementById( 'hero-' + game );


     /* 先把新slide的fg重置为缩放状态,让Ken Burns重新触发 */
     /* Ken Burns重置 */
     if ( inSlide ) {
     if ( inSlide ) {
       var inFg = inSlide.querySelector( '.gf-hero-fg' );
       var inFg = inSlide.querySelector( '.gf-hero-fg' );
       if ( inFg ) {
       if ( inFg ) {
         inFg.style.transition = 'none';
         inFg.style.transition = 'none';
         inFg.style.transform = window.innerWidth > 1200
         inFg.style.transform = window.innerWidth > 1200
           ? 'translateX(-50%) scale(1.06)'
           ? 'translateX(-50%) scale(1.06)'
           : 'scale(1.06)';
           : 'scale(1.06)';
第95行: 第92行:
     }
     }


     /* tab状态 */
     /* tab与指示器立即响应,不等动画 */
     tabs.forEach( function ( t ) {
     tabs.forEach( function ( t ) {
       var on = t.getAttribute( 'data-game' ) === game;
       var on = t.getAttribute( 'data-game' ) === game;
第101行: 第98行:
       t.setAttribute( 'aria-selected', on ? 'true' : 'false' );
       t.setAttribute( 'aria-selected', on ? 'true' : 'false' );
     } );
     } );
    /* 滑动指示器 */
     if ( tabEl ) { moveIndicator( tabEl ); }
     if ( tabEl ) { moveIndicator( tabEl ); }


     /* 内容面板 */
     /* 内容面板立即切换 */
     panels.forEach( function ( p ) {
     panels.forEach( function ( p ) {
       p.classList.toggle( 'active', p.id === 'content-' + game );
       p.classList.toggle( 'active', p.id === 'content-' + game );
     } );
     } );
    currentGame = game;
    switching  = true;


     setTimeout( function () {
     setTimeout( function () {
       slides.forEach( function ( s ) {
       slides.forEach( function ( s ) { s.style.zIndex = ''; } );
        s.style.zIndex = '';
      } );
      currentGame = game;
       switching = false;
       switching = false;
      /* 动画结束后执行期间积压的最后一次请求 */
      if ( pending && pending.game !== currentGame ) {
        var p = pending;
        pending = null;
        doSwitch( p.game, p.tabEl );
      } else {
        pending = null;
      }
     }, 720 );
     }, 720 );
  }
  function switchGame( game, tabEl ) {
    if ( game === currentGame ) { return; }
    if ( switching ) {
      /* 记录最新目标,覆盖之前积压的 */
      pending = { game: game, tabEl: tabEl };
      /* 指示器和tab状态立即跟手 */
      var tabs = document.querySelectorAll( '#gf-homepage .gf-tab' );
      tabs.forEach( function ( t ) {
        var on = t.getAttribute( 'data-game' ) === game;
        t.classList.toggle( 'active', on );
        t.setAttribute( 'aria-selected', on ? 'true' : 'false' );
      } );
      if ( tabEl ) { moveIndicator( tabEl ); }
      return;
    }
    doSwitch( game, tabEl );
   }
   }


第123行: 第145行:
     if ( !tabs.length ) { return; }
     if ( !tabs.length ) { return; }


    /* 注入背景图 */
     Object.keys( heroImages ).forEach( function ( game ) {
     Object.keys( heroImages ).forEach( function ( game ) {
       getWikiImageUrl( heroImages[ game ], function ( url ) {
       getWikiImageUrl( heroImages[ game ], function ( url ) {
         var bg = document.getElementById( 'hero-' + game + '-bg' );
         var bg = document.getElementById( 'hero-' + game + '-bg' );
         var fg = document.getElementById( 'hero-' + game + '-fg' );
         var fg = document.getElementById( 'hero-' + game + '-fg' );
         var val = 'url("' + url + '")';
         var val = 'url("' + url + '")';
         if ( bg ) { bg.style.backgroundImage = val; }
         if ( bg ) { bg.style.backgroundImage = val; }
第136行: 第157行:
     applyFadeColor();
     applyFadeColor();


    /* 初始化指示器位置 */
     var firstActive = document.querySelector( '#gf-homepage .gf-tab.active' );
     var firstActive = document.querySelector( '#gf-homepage .gf-tab.active' );
     if ( firstActive ) {
     if ( firstActive ) {
      /* 等布局稳定后再计算 */
       setTimeout( function () { moveIndicator( firstActive ); }, 50 );
       setTimeout( function () { moveIndicator( firstActive ); }, 50 );
     }
     }
第155行: 第174行:
     } );
     } );


    /* 窗口resize时重新定位指示器 */
     window.addEventListener( 'resize', function () {
     window.addEventListener( 'resize', function () {
       var active = document.querySelector( '#gf-homepage .gf-tab.active' );
       var active = document.querySelector( '#gf-homepage .gf-tab.active' );

2026年6月20日 (六) 22:15的版本

本Widget为少女前线系列多游戏首页提供切换交互逻辑。 不接受参数,直接在首页调用:{{#widget:GFHomepageSwitcher}}