Widget:GameSwitcher:修订间差异
来自OGAS数据中枢
更多操作
无编辑摘要 |
无编辑摘要 |
||
| 第3行: | 第3行: | ||
不接受参数,直接在首页调用:<code><nowiki>{{#widget:GFHomepageSwitcher}}</nowiki></code> | 不接受参数,直接在首页调用:<code><nowiki>{{#widget:GFHomepageSwitcher}}</nowiki></code> | ||
</noinclude><includeonly><script> | </noinclude><includeonly><script> | ||
(function () { | ( function () { | ||
'use strict'; | 'use strict'; | ||
| 第16行: | 第16行: | ||
var canonical = document.querySelector( 'link[rel="canonical"]' ); | var canonical = document.querySelector( 'link[rel="canonical"]' ); | ||
if ( canonical ) { | if ( canonical ) { | ||
var | var m = canonical.href.match( /^(https?:\/\/[^\/]+(?:\/[^\/]+)*?)\/wiki\// ); | ||
if ( | if ( m ) { return m[ 1 ] + '/api.php'; } | ||
} | } | ||
return window.location.origin + '/api.php'; | return window.location.origin + '/api.php'; | ||
| 第28行: | 第28行: | ||
.then( function ( data ) { | .then( function ( data ) { | ||
var pages = data.query.pages; | var pages = data.query.pages; | ||
var page | var page = pages[ Object.keys( pages )[ 0 ] ]; | ||
if ( page.imageinfo && page.imageinfo[ 0 ] ) { | if ( page.imageinfo && page.imageinfo[ 0 ] ) { | ||
callback( page.imageinfo[ 0 ].url ); | callback( page.imageinfo[ 0 ].url ); | ||
| 第36行: | 第36行: | ||
} | } | ||
function | function applyFadeColor() { | ||
var style = getComputedStyle( document.documentElement ); | var style = getComputedStyle( document.documentElement ); | ||
var bg = style.getPropertyValue( '--color-surface-0' ).trim() | var bg = style.getPropertyValue( '--color-surface-0' ).trim() | ||
| 第45行: | 第45行: | ||
el.style.background = 'linear-gradient(to bottom, transparent 0%, ' + bg + ' 100%)'; | el.style.background = 'linear-gradient(to bottom, transparent 0%, ' + bg + ' 100%)'; | ||
} | } | ||
} | |||
/* 滑动指示器:根据当前active tab的位置和宽度移动 */ | |||
function moveIndicator( tab ) { | |||
var indicator = document.getElementById( 'gf-tab-indicator' ); | |||
var switcher = document.getElementById( 'gf-switcher' ); | |||
if ( !indicator || !switcher ) { return; } | |||
var switcherRect = switcher.getBoundingClientRect(); | |||
var tabRect = tab.getBoundingClientRect(); | |||
indicator.style.width = tabRect.width + 'px'; | |||
indicator.style.transform = 'translateX(' + ( tabRect.left - switcherRect.left ) + 'px)'; | |||
} | } | ||
| 第50行: | 第61行: | ||
var switching = false; | var switching = false; | ||
function switchGame( game ) { | function switchGame( game, tabEl ) { | ||
if ( game === currentGame || switching ) { return; } | if ( game === currentGame || switching ) { return; } | ||
switching = true; | switching = true; | ||
var slides | var slides = document.querySelectorAll( '#gf-homepage .gf-hero-slide' ); | ||
var panels | var panels = document.querySelectorAll( '#gf-homepage .gf-content-panel' ); | ||
var tabs | var tabs = document.querySelectorAll( '#gf-homepage .gf-tab' ); | ||
var outSlide = document.getElementById( 'hero-' + currentGame ); | var outSlide = document.getElementById( 'hero-' + currentGame ); | ||
var inSlide = document.getElementById( 'hero-' + game ); | var inSlide = document.getElementById( 'hero-' + game ); | ||
/* 先把新slide的fg重置为缩放状态,让Ken Burns重新触发 */ | |||
if ( inSlide ) { | if ( inSlide ) { | ||
inSlide.style. | var inFg = inSlide.querySelector( '.gf-hero-fg' ); | ||
if ( inFg ) { | |||
inFg.style.transition = 'none'; | |||
inFg.style.transform = window.innerWidth > 1200 | |||
inSlide.style. | ? 'translateX(-50%) scale(1.06)' | ||
: 'scale(1.06)'; | |||
void inFg.offsetWidth; | |||
inFg.style.transition = ''; | |||
} | |||
} | |||
/* 交叉淡入淡出 */ | |||
if ( inSlide ) { | |||
inSlide.style.zIndex = '1'; | |||
inSlide.classList.add( 'active' ); | |||
} | } | ||
if ( outSlide ) { | if ( outSlide ) { | ||
outSlide.style.zIndex | outSlide.style.zIndex = '0'; | ||
outSlide. | outSlide.classList.remove( 'active' ); | ||
} | } | ||
/* tab状态 */ | |||
tabs.forEach( function ( t ) { | tabs.forEach( function ( t ) { | ||
var on = t.getAttribute( 'data-game' ) === game; | var on = t.getAttribute( 'data-game' ) === game; | ||
t.classList.toggle( 'active', on ); | t.classList.toggle( 'active', on ); | ||
t.setAttribute( 'aria-selected', on ? 'true' : 'false' ); | t.setAttribute( 'aria-selected', on ? 'true' : 'false' ); | ||
} ); | |||
/* 滑动指示器 */ | |||
if ( tabEl ) { moveIndicator( tabEl ); } | |||
/* 内容面板 */ | |||
panels.forEach( function ( p ) { | |||
p.classList.toggle( 'active', p.id === 'content-' + game ); | |||
} ); | } ); | ||
setTimeout( function () { | setTimeout( function () { | ||
slides.forEach( function ( s ) { | slides.forEach( function ( s ) { | ||
s.style.zIndex | s.style.zIndex = ''; | ||
} ); | } ); | ||
currentGame = game; | currentGame = game; | ||
switching | switching = false; | ||
}, | }, 720 ); | ||
} | } | ||
| 第101行: | 第123行: | ||
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 ) { | ||
| 第112行: | 第134行: | ||
} ); | } ); | ||
applyFadeColor(); | |||
/* 初始化指示器位置 */ | |||
var firstActive = document.querySelector( '#gf-homepage .gf-tab.active' ); | |||
if ( firstActive ) { | |||
/* 等布局稳定后再计算 */ | |||
setTimeout( function () { moveIndicator( firstActive ); }, 50 ); | |||
} | |||
tabs.forEach( function ( tab ) { | tabs.forEach( function ( tab ) { | ||
tab.addEventListener( 'click', function () { | tab.addEventListener( 'click', function () { | ||
switchGame( this.getAttribute( 'data-game' ) ); | switchGame( this.getAttribute( 'data-game' ), this ); | ||
} ); | } ); | ||
tab.addEventListener( 'keydown', function ( e ) { | tab.addEventListener( 'keydown', function ( e ) { | ||
if ( e.key === 'Enter' || e.key === ' ' ) { | if ( e.key === 'Enter' || e.key === ' ' ) { | ||
e.preventDefault(); | e.preventDefault(); | ||
switchGame( this.getAttribute( 'data-game' ) ); | switchGame( this.getAttribute( 'data-game' ), this ); | ||
} | } | ||
} ); | } ); | ||
} ); | |||
/* 窗口resize时重新定位指示器 */ | |||
window.addEventListener( 'resize', function () { | |||
var active = document.querySelector( '#gf-homepage .gf-tab.active' ); | |||
if ( active ) { moveIndicator( active ); } | |||
} ); | } ); | ||
} | } | ||
2026年6月20日 (六) 22:14的版本
本Widget为少女前线系列多游戏首页提供切换交互逻辑。
不接受参数,直接在首页调用:{{#widget:GFHomepageSwitcher}}