打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Citizen.js:修订间差异

MediaWiki界面页面
OnlyOTO留言 | 贡献
创建页面,内容为“这里所有JavaScript都会加载给Citizen皮肤的用户:​ (function() { mw.loader.using('jquery', function() { $(function() { // 防重复挂载 if (document.querySelector('.magnetic-pointer-original')) return; // 创建光标DOM const pointer = document.createElement('div'); pointer.className = 'magnetic-pointer-original'; pointer.innerHTML = '<div></div><div></div><di…”
 
OnlyOTO留言 | 贡献
无编辑摘要
第3行: 第3行:
     mw.loader.using('jquery', function() {
     mw.loader.using('jquery', function() {
         $(function() {
         $(function() {
            // 防重复挂载
             if (document.querySelector('.magnetic-pointer-original')) return;
             if (document.querySelector('.magnetic-pointer-original')) return;


             // 创建光标DOM
             // 光标 DOM
             const pointer = document.createElement('div');
             const pointer = document.createElement('div');
             pointer.className = 'magnetic-pointer-original';
             pointer.className = 'magnetic-pointer-original';
第12行: 第11行:
             document.body.appendChild(pointer);
             document.body.appendChild(pointer);


             // 终极修复CSS:纯镂空四角 + 适配Citizen层级
             // 样式:纯空心四角角标
             const style = document.createElement('style');
             const style = document.createElement('style');
             style.textContent = `
             style.textContent = `
/* 光标本体 */
.magnetic-pointer-original {
.magnetic-pointer-original {
     --width: 4rem;
     --width: 48px;
     --height: 4rem;
     --height: 48px;
     position: fixed;
     position: fixed;
     top: calc(var(--height) / -2);
     top: 0;
     left: calc(var(--width) / -2);
     left: 0;
     width: var(--width);
     width: var(--width);
     height: var(--height);
     height: var(--height);
     transition: all 0.2s ease-out;
    transform-origin: center center;
     pointer-events: none;
     transition: transform 0.22s ease, width 0.22s ease, height 0.22s ease;
     z-index: 999999 !important; /* 压过Citizen所有弹窗/导航 */
     pointer-events: none !important;
     z-index: 999999 !important;
    will-change: transform, width, height;
}
}
/* 四角拐角 - 杜绝方块 */
.magnetic-pointer-original div {
.magnetic-pointer-original div {
     position: absolute;
     position: absolute;
第35行: 第34行:
     border-color: #17f700;
     border-color: #17f700;
     background: transparent !important;
     background: transparent !important;
     box-shadow: none !important;
     box-sizing: border-box;
    margin: 0 !important;
    padding: 0 !important;
}
.magnetic-pointer-original div:nth-child(1) {top:0;left:0;border-top:2px solid;border-left:2px solid;}
.magnetic-pointer-original div:nth-child(2) {top:0;right:0;border-top:2px solid;border-right:2px solid;}
.magnetic-pointer-original div:nth-child(3) {bottom:0;left:0;border-bottom:2px solid;border-left:2px solid;}
.magnetic-pointer-original div:nth-child(4) {bottom:0;right:0;border-bottom:2px solid;border-right:2px solid;}
 
/* 锁定Citizen皮肤所有按钮为磁吸目标 */
.citizen-button,
.citizen-ui-button,
.citizen-nav-item a,
.citizen-menu-item a,
#citizen-header a,
#citizen-sidebar a,
.vector-tabs a,
.mw-editsection,
a.citizen-link-button {
    position: relative !important;
}
}
.magnetic-pointer-original div:nth-child(1) { top: 0; left: 0; border-top: 2px solid; border-left: 2px solid; }
.magnetic-pointer-original div:nth-child(2) { top: 0; right: 0; border-top: 2px solid; border-right: 2px solid; }
.magnetic-pointer-original div:nth-child(3) { bottom: 0; left: 0; border-bottom: 2px solid; border-left: 2px solid; }
.magnetic-pointer-original div:nth-child(4) { bottom: 0; right: 0; border-bottom: 2px solid; border-right: 2px solid; }
             `;
             `;
             document.head.appendChild(style);
             document.head.appendChild(style);


             let currentTarget = null;
             let target = null;
             let currentX = 0, currentY = 0;
             let mouseX = 0, mouseY = 0;
            let cursorX = 0, cursorY = 0;
 
            // 鼠标位置实时更新
            window.addEventListener('mousemove', (e) => {
                mouseX = e.clientX;
                mouseY = e.clientY;
            });
 
            // 平滑跟随循环
            function update() {
                if (target) {
                    const rect = target.getBoundingClientRect();
                    const cx = rect.left + rect.width / 2;
                    const cy = rect.top + rect.height / 2;
 
                    cursorX += (cx - cursorX) * 0.2;
                    cursorY += (cy - cursorY) * 0.2;


            // 磁吸跟随逻辑
                    pointer.style.width = rect.width + 12 + 'px';
            const onMouseMove = function(e) {
                     pointer.style.height = rect.height + 12 + 'px';
                let x = e.clientX;
                } else {
                let y = e.clientY;
                     cursorX += (mouseX - cursorX) * 0.25;
                if (currentTarget) {
                     cursorY += (mouseY - cursorY) * 0.25;
                    const rect = currentTarget.getBoundingClientRect();
                    pointer.style.width = '48px';
                     const centerX = rect.left + rect.width / 2;
                    pointer.style.height = '48px';
                    const centerY = rect.top + rect.height / 2;
                     x = centerX + (x - centerX) * 0.12; // 微调吸附顺滑度
                     y = centerY + (y - centerY) * 0.12;
                 }
                 }
                currentX = x;
                currentY = y;
                pointer.style.transform = `translate(${currentX}px, ${currentY}px)`;
            };


            const onMouseEnter = function(e) {
                pointer.style.transform = `translate(${cursorX - pointer.offsetWidth/2}px, ${cursorY - pointer.offsetHeight/2}px)`;
                 currentTarget = e.currentTarget;
                 requestAnimationFrame(update);
                const rect = currentTarget.getBoundingClientRect();
            }
                // 贴合Citizen按钮间距,放大留白更自然
            update();
                const gap = window.innerWidth / 60;
 
                 pointer.style.setProperty('--width', rect.width + gap + 'px');
            // 👇 这是 Citizen 皮肤真正的按钮选择器(全覆盖)
                 pointer.style.setProperty('--height', rect.height + gap + 'px');
            const citizenSelectors = [
             };
                ".citizen-button",
                ".citizen-ui-btn",
                 ".citizen-nav__item a",
                ".citizen-menu__item a",
                "#citizen-header a",
                "#citizen-sidebar a",
                "a.citizen-button",
                "button.citizen-button",
                 ".mw-editsection a",
                ".mw-ui-button",
                ".citizen-btn"
             ].join(",");


             const onMouseLeave = function() {
             function bind() {
                 currentTarget = null;
                 document.querySelectorAll(citizenSelectors).forEach(el => {
                pointer.style.setProperty('--width', '4rem');
                    if (el._magnet) return;
                pointer.style.setProperty('--height', '4rem');
                    el._magnet = 1;
            };


            // 自动绑定:Citizen全系列按钮 + 原有自定义_target
                     el.addEventListener("mouseenter", () => {
            const bindCitizenButtons = function() {
                        target = el;
                const selector = `
                     });
                     .citizen-button:not([data-bound]),
                     el.addEventListener("mouseleave", () => {
                    .citizen-ui-button:not([data-bound]),
                        target = null;
                    .citizen-nav-item a:not([data-bound]),
                     });
                     .citizen-menu-item a:not([data-bound]),
                    #citizen-header a:not([data-bound]),
                    #citizen-sidebar a:not([data-bound]),
                     .mw-editsection:not([data-bound]),
                    a.citizen-link-button:not([data-bound]),
                    ._target:not([data-bound])
                `;
                document.querySelectorAll(selector).forEach(el => {
                    el.dataset.bound = "1";
                    el.addEventListener('mouseenter', onMouseEnter);
                     el.addEventListener('mouseleave', onMouseLeave);
                 });
                 });
             };
             }
 
            // 全局鼠标监听
            window.addEventListener('mousemove', onMouseMove);
 
            // 初始绑定
            bindCitizenButtons();


             // 监听动态加载(侧边栏折叠/展开、AJAX页面、弹窗)
             bind();
             const observer = new MutationObserver(() => bindCitizenButtons());
             new MutationObserver(bind).observe(document.body, { childList: true, subtree: true });
            observer.observe(document.body, { childList: true, subtree: true, attributes: true });
         });
         });
     });
     });
})();
})();

2026年3月31日 (二) 15:58的版本

/* 这里所有JavaScript都会加载给Citizen皮肤的用户 */
(function() {
    mw.loader.using('jquery', function() {
        $(function() {
            if (document.querySelector('.magnetic-pointer-original')) return;

            // 光标 DOM
            const pointer = document.createElement('div');
            pointer.className = 'magnetic-pointer-original';
            pointer.innerHTML = '<div></div><div></div><div></div><div></div>';
            document.body.appendChild(pointer);

            // 样式:纯空心四角角标
            const style = document.createElement('style');
            style.textContent = `
.magnetic-pointer-original {
    --width: 48px;
    --height: 48px;
    position: fixed;
    top: 0;
    left: 0;
    width: var(--width);
    height: var(--height);
    transform-origin: center center;
    transition: transform 0.22s ease, width 0.22s ease, height 0.22s ease;
    pointer-events: none !important;
    z-index: 999999 !important;
    will-change: transform, width, height;
}
.magnetic-pointer-original div {
    position: absolute;
    width: 12px;
    height: 12px;
    border-color: #17f700;
    background: transparent !important;
    box-sizing: border-box;
}
.magnetic-pointer-original div:nth-child(1) { top: 0; left: 0; border-top: 2px solid; border-left: 2px solid; }
.magnetic-pointer-original div:nth-child(2) { top: 0; right: 0; border-top: 2px solid; border-right: 2px solid; }
.magnetic-pointer-original div:nth-child(3) { bottom: 0; left: 0; border-bottom: 2px solid; border-left: 2px solid; }
.magnetic-pointer-original div:nth-child(4) { bottom: 0; right: 0; border-bottom: 2px solid; border-right: 2px solid; }
            `;
            document.head.appendChild(style);

            let target = null;
            let mouseX = 0, mouseY = 0;
            let cursorX = 0, cursorY = 0;

            // 鼠标位置实时更新
            window.addEventListener('mousemove', (e) => {
                mouseX = e.clientX;
                mouseY = e.clientY;
            });

            // 平滑跟随循环
            function update() {
                if (target) {
                    const rect = target.getBoundingClientRect();
                    const cx = rect.left + rect.width / 2;
                    const cy = rect.top + rect.height / 2;

                    cursorX += (cx - cursorX) * 0.2;
                    cursorY += (cy - cursorY) * 0.2;

                    pointer.style.width = rect.width + 12 + 'px';
                    pointer.style.height = rect.height + 12 + 'px';
                } else {
                    cursorX += (mouseX - cursorX) * 0.25;
                    cursorY += (mouseY - cursorY) * 0.25;
                    pointer.style.width = '48px';
                    pointer.style.height = '48px';
                }

                pointer.style.transform = `translate(${cursorX - pointer.offsetWidth/2}px, ${cursorY - pointer.offsetHeight/2}px)`;
                requestAnimationFrame(update);
            }
            update();

            // 👇 这是 Citizen 皮肤真正的按钮选择器(全覆盖)
            const citizenSelectors = [
                ".citizen-button",
                ".citizen-ui-btn",
                ".citizen-nav__item a",
                ".citizen-menu__item a",
                "#citizen-header a",
                "#citizen-sidebar a",
                "a.citizen-button",
                "button.citizen-button",
                ".mw-editsection a",
                ".mw-ui-button",
                ".citizen-btn"
            ].join(",");

            function bind() {
                document.querySelectorAll(citizenSelectors).forEach(el => {
                    if (el._magnet) return;
                    el._magnet = 1;

                    el.addEventListener("mouseenter", () => {
                        target = el;
                    });
                    el.addEventListener("mouseleave", () => {
                        target = null;
                    });
                });
            }

            bind();
            new MutationObserver(bind).observe(document.body, { childList: true, subtree: true });
        });
    });
})();