MediaWiki:Common.js:修订间差异
MediaWiki界面页面
更多操作
无编辑摘要 标签:手工回退 |
无编辑摘要 |
||
| 第109行: | 第109行: | ||
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); | observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); | ||
})(); | |||
/* ============================================== */ | |||
/* --- Section25.Wiki 弹出预览菜单动画控制 --- */ | |||
/* ============================================== */ | |||
(function() { | |||
'use strict'; | |||
// 配置 | |||
const CONFIG = { | |||
enableEnterAnimation: true, // 弹出动画开关 | |||
enableExitAnimation: true, // 消失动画开关(如果有问题可以改为 false) | |||
animationDuration: 250, // 弹出动画时长(ms) | |||
exitDuration: 200 // 消失动画时长(ms) | |||
}; | |||
// 监听弹窗显示 | |||
const observer = new MutationObserver((mutations) => { | |||
mutations.forEach((mutation) => { | |||
mutation.addedNodes.forEach((node) => { | |||
if (node.classList && node.classList.contains('mwe-popups')) { | |||
handlePopupShow(node); | |||
} | |||
}); | |||
}); | |||
// 监听样式变化(弹窗显示) | |||
mutations.forEach((mutation) => { | |||
if (mutation.type === 'attributes' && mutation.attributeName === 'style') { | |||
const popup = mutation.target; | |||
if (popup.classList && popup.classList.contains('mwe-popups')) { | |||
const isVisible = popup.style.display === 'block'; | |||
if (isVisible && !popup.dataset.animated) { | |||
handlePopupShow(popup); | |||
} | |||
} | |||
} | |||
}); | |||
}); | |||
// 处理弹窗显示 | |||
function handlePopupShow(popup) { | |||
if (!CONFIG.enableEnterAnimation) return; | |||
// 标记已处理 | |||
popup.dataset.customAnimation = 'true'; | |||
popup.dataset.animated = 'true'; | |||
// 判断弹出方向(根据 class) | |||
const isFlippedY = popup.classList.contains('flipped-y'); | |||
const animationClass = isFlippedY ? 'popup-animating-in-up' : 'popup-animating-in-down'; | |||
// 添加动画class | |||
popup.classList.add(animationClass); | |||
// 动画结束后移除class | |||
setTimeout(() => { | |||
popup.classList.remove(animationClass); | |||
}, CONFIG.animationDuration); | |||
// 监听弹窗隐藏(用于退出动画) | |||
if (CONFIG.enableExitAnimation) { | |||
observePopupHide(popup); | |||
} | |||
} | |||
// 监听弹窗隐藏 | |||
function observePopupHide(popup) { | |||
const hideObserver = new MutationObserver((mutations) => { | |||
mutations.forEach((mutation) => { | |||
if (mutation.type === 'attributes' && mutation.attributeName === 'style') { | |||
const isHidden = popup.style.display === 'none' || popup.style.display === ''; | |||
if (isHidden && popup.dataset.animated === 'true') { | |||
hideObserver.disconnect(); | |||
handlePopupHide(popup); | |||
} | |||
} | |||
}); | |||
}); | |||
hideObserver.observe(popup, { | |||
attributes: true, | |||
attributeFilter: ['style'] | |||
}); | |||
} | |||
// 处理弹窗隐藏 | |||
function handlePopupHide(popup) { | |||
// 先恢复显示以播放退出动画 | |||
const originalDisplay = popup.style.display; | |||
popup.style.display = 'block'; | |||
// 判断退出方向 | |||
const isFlippedY = popup.classList.contains('flipped-y'); | |||
const animationClass = isFlippedY ? 'popup-animating-out-up' : 'popup-animating-out-down'; | |||
// 添加退出动画 | |||
popup.classList.add(animationClass); | |||
// 动画结束后真正隐藏 | |||
setTimeout(() => { | |||
popup.style.display = originalDisplay; | |||
popup.classList.remove(animationClass); | |||
popup.dataset.animated = ''; | |||
}, CONFIG.exitDuration); | |||
} | |||
// 开始监听 | |||
observer.observe(document.body, { | |||
childList: true, | |||
subtree: true, | |||
attributes: true, | |||
attributeFilter: ['style'] | |||
}); | |||
console.log('✅ Wiki弹窗动画已启用'); | |||
})(); | })(); | ||
2026年2月22日 (日) 17:36的版本
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
/**
* 搜索面板弹性动画逻辑
*/
(function() {
function handlePalette() {
const palette = document.querySelector('.citizen-command-palette');
if (palette) {
// 确保位置居中并触发动画类
if (!palette.classList.contains('glass-show')) {
palette.classList.add('glass-show');
}
} else {
// 当面板关闭时,移除所有带有 glass-show 的残留(虽然通常会被销毁)
const activePalettes = document.querySelectorAll('.glass-show');
activePalettes.forEach(p => p.classList.remove('glass-show'));
}
}
// 每 50ms 检查一次搜索框状态(保持和 V20 脚本逻辑一致)
setInterval(handlePalette, 50);
})();
// 在 MediaWiki:Common.js 中尝试
$(function() {
if ($('#p-navigation').length) {
var adHtml = '<div id="sidebar-ad"></div>';
$('#p-navigation').after(adHtml);
// 使用 API 获取解析后的模板内容并注入
$.get(mw.util.wikiScript('api'), {
action: 'parse',
text: '{{CitizenAd}}',
format: 'json'
}, function(data) {
$('#sidebar-ad').html(data.parse.text['*']);
});
}
});
/**
* Blockland Wiki Liquid Glass Lighting System
* 全局液态玻璃光影联动系统
*/
(function() {
'use strict';
// 1. 判定开关:检查是否开启了性能模式(Basic)
// 这里的类名对应你反馈的 citizen-feature-performance-mode-clientpref-1
const isPerformanceMode = () => {
return document.documentElement.classList.contains('citizen-feature-performance-mode-clientpref-1');
};
// 2. 目标选择器(包含目录 ID 和通用卡片类名)
const GLASS_SELECTORS = '#mw-panel-toc, #citizen-sidebar-lastmod, .citizen-menu__card, .citizen-toc-card, .citizen-command-palette, .infobox';
const syncLight = (e) => {
// 如果是性能模式,直接退出,不消耗任何 CPU
if (isPerformanceMode()) return;
const elements = document.querySelectorAll(GLASS_SELECTORS);
elements.forEach(el => {
const rect = el.getBoundingClientRect();
// 只有当元素在视口内且宽度不为 0 时才计算(性能优化)
if (rect.width > 0 && rect.top < window.innerHeight && rect.bottom > 0) {
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;
// 注入坐标变量
el.style.setProperty('--mouse-x', x.toFixed(2) + '%');
el.style.setProperty('--mouse-y', y.toFixed(2) + '%');
}
});
};
// 3. 搜索面板 glass-show 逻辑整合
// 即使在性能模式,也可以保留简单的显示逻辑,或者一同禁用
const paletteCheck = setInterval(() => {
if (isPerformanceMode()) return;
const p = document.querySelector('.citizen-command-palette');
if (p && !p.classList.contains('glass-show')) {
p.classList.add('glass-show');
}
}, 100);
// 4. 事件监听(使用 requestAnimationFrame 保证丝滑)
let ticking = false;
document.addEventListener('mousemove', (e) => {
if (isPerformanceMode()) return;
if (!ticking) {
window.requestAnimationFrame(() => {
syncLight(e);
ticking = false;
});
ticking = true;
}
}, { passive: true });
// 5. 额外:当用户手动切换模式时清除变量(可选)
// 防止从 Aero 切换到 Basic 时光效残留在一半的位置
const observer = new MutationObserver(() => {
if (isPerformanceMode()) {
document.querySelectorAll(GLASS_SELECTORS).forEach(el => {
el.style.removeProperty('--mouse-x');
el.style.removeProperty('--mouse-y');
});
}
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
})();
/* ============================================== */
/* --- Section25.Wiki 弹出预览菜单动画控制 --- */
/* ============================================== */
(function() {
'use strict';
// 配置
const CONFIG = {
enableEnterAnimation: true, // 弹出动画开关
enableExitAnimation: true, // 消失动画开关(如果有问题可以改为 false)
animationDuration: 250, // 弹出动画时长(ms)
exitDuration: 200 // 消失动画时长(ms)
};
// 监听弹窗显示
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.classList && node.classList.contains('mwe-popups')) {
handlePopupShow(node);
}
});
});
// 监听样式变化(弹窗显示)
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
const popup = mutation.target;
if (popup.classList && popup.classList.contains('mwe-popups')) {
const isVisible = popup.style.display === 'block';
if (isVisible && !popup.dataset.animated) {
handlePopupShow(popup);
}
}
}
});
});
// 处理弹窗显示
function handlePopupShow(popup) {
if (!CONFIG.enableEnterAnimation) return;
// 标记已处理
popup.dataset.customAnimation = 'true';
popup.dataset.animated = 'true';
// 判断弹出方向(根据 class)
const isFlippedY = popup.classList.contains('flipped-y');
const animationClass = isFlippedY ? 'popup-animating-in-up' : 'popup-animating-in-down';
// 添加动画class
popup.classList.add(animationClass);
// 动画结束后移除class
setTimeout(() => {
popup.classList.remove(animationClass);
}, CONFIG.animationDuration);
// 监听弹窗隐藏(用于退出动画)
if (CONFIG.enableExitAnimation) {
observePopupHide(popup);
}
}
// 监听弹窗隐藏
function observePopupHide(popup) {
const hideObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
const isHidden = popup.style.display === 'none' || popup.style.display === '';
if (isHidden && popup.dataset.animated === 'true') {
hideObserver.disconnect();
handlePopupHide(popup);
}
}
});
});
hideObserver.observe(popup, {
attributes: true,
attributeFilter: ['style']
});
}
// 处理弹窗隐藏
function handlePopupHide(popup) {
// 先恢复显示以播放退出动画
const originalDisplay = popup.style.display;
popup.style.display = 'block';
// 判断退出方向
const isFlippedY = popup.classList.contains('flipped-y');
const animationClass = isFlippedY ? 'popup-animating-out-up' : 'popup-animating-out-down';
// 添加退出动画
popup.classList.add(animationClass);
// 动画结束后真正隐藏
setTimeout(() => {
popup.style.display = originalDisplay;
popup.classList.remove(animationClass);
popup.dataset.animated = '';
}, CONFIG.exitDuration);
}
// 开始监听
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style']
});
console.log('✅ Wiki弹窗动画已启用');
})();