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

MediaWiki:Citizen.js:修订间差异

MediaWiki界面页面
OnlyOTO留言 | 贡献
无编辑摘要
OnlyOTO留言 | 贡献
无编辑摘要
第1行: 第1行:
(function() {
(function() {
if( window.magneticCursorInit ) return;
    mw.loader.using('jquery', function() {
window.magneticCursorInit = true;
        $(function() {
            if (document.querySelector('.magnetic-pointer-original')) return;


mw.loader.using( [], function() {
            const pointer = document.createElement('div');
    const ptr = document.createElement('div');
            pointer.className = 'magnetic-pointer-original';
    ptr.className = 'magnetic-true-corner';
            pointer.innerHTML = '<div></div><div></div><div></div><div></div>';
    ptr.innerHTML = `<i></i><i></i><i></i><i></i>`;
            document.body.appendChild(pointer);
    document.body.appendChild(ptr);


    const css = document.createElement('style');
            const style = document.createElement('style');
    css.textContent = `
            style.textContent = `
/* 浅色模式:原版亮绿 */
.magnetic-pointer-original {
.magnetic-true-corner i{
    --width: 4rem;
     position:absolute;
    --height: 4rem;
     width:14px;height:14px;
     position: fixed;
     border:2px solid #17f700;
    top: calc(var(--height) / -2);
     background:transparent!important;
    left: calc(var(--width) / -2);
     box-shadow:none!important;
     width: var(--width);
    height: var(--height);
     transition: all 0.2s ease-out;
     pointer-events: none;
     z-index: 99999;
}
}
/* ========== Citizen 真正暗黑模式精准匹配 ========== */
/* 白天模式:绿色 */
html[data-color-scheme="dark"] .magnetic-true-corner i {
.magnetic-pointer-original div {
     border-color: #4fc3f7 !important;
    position: absolute;
    width: 0.8rem;
    height: 0.8rem;
     border-color: #17f700;
    background: transparent !important;
    border-top:3px solid transparent;
    border-left:3px solid transparent;
}
}
 
/* 黑夜模式:白色 */
.magnetic-true-corner{
html[data-color-scheme="dark"] .magnetic-pointer-original div {
     position:fixed;
     border-color: #ffffff !important;
    left:0;top:0;
    width:0;height:0;
    pointer-events:none;
    z-index:999999!important;
}
}
.magnetic-true-corner i:nth-child(1){top:-2px;left:-2px;border-right:none;border-bottom:none;}
.magnetic-true-corner i:nth-child(2){top:-2px;right:-2px;border-left:none;border-bottom:none;}
.magnetic-true-corner i:nth-child(3){bottom:-2px;left:-2px;border-right:none;border-top:none;}
.magnetic-true-corner i:nth-child(4){bottom:-2px;right:-2px;border-left:none;border-top:none;}
    `;
    document.head.appendChild(css);


    let hoverEl = null;
.magnetic-pointer-original div:nth-child(1) {top:0;left:0;border-top-color:inherit;border-left-color:inherit;}
    let mx = 0, my = 0;
.magnetic-pointer-original div:nth-child(2) {top:0;right:0;border-top-color:inherit;border-right-color:inherit;}
    let smoothX = 0, smoothY = 0;
.magnetic-pointer-original div:nth-child(3) {bottom:0;left:0;border-bottom-color:inherit;border-left-color:inherit;}
    let curW = 40, curH = 40;
.magnetic-pointer-original div:nth-child(4) {bottom:0;right:0;border-bottom-color:inherit;border-right-color:inherit;}
            `;
            document.head.appendChild(style);


    document.addEventListener('mousemove', e => {
            let currentTarget = null;
        mx = e.clientX;
            let currentX = 0, currentY = 0;
        my = e.clientY;
    });


    function loop(){
            const onMouseMove = function(e) {
        const ease = 0.15;
                let x = e.clientX;
        if(hoverEl){
                let y = e.clientY;
            const r = hoverEl.getBoundingClientRect();
                if (currentTarget) {
            const targetX = r.left + r.width / 2;
                    const rect = currentTarget.getBoundingClientRect();
            const targetY = r.top + r.height / 2;
                    const centerX = rect.left + rect.width / 2;
            smoothX += (targetX - smoothX) * ease;
                    const centerY = rect.top + rect.height / 2;
            smoothY += (targetY - smoothY) * ease;
                    x = centerX + (x - centerX) * 0.1;
            curW = r.width;
                    y = centerY + (y - centerY) * 0.1;
             curH = r.height;
                }
                currentX = x;
                currentY = y;
                pointer.style.transform = `translate(${currentX}px, ${currentY}px)`;
             };


             ptr.style.left = (smoothX - curW / 2) + 'px';
             const onMouseEnter = function(e) {
            ptr.style.top = (smoothY - curH / 2) + 'px';
                currentTarget = e.currentTarget;
            ptr.style.width = curW + 'px';
                const rect = currentTarget.getBoundingClientRect();
            ptr.style.height = curH + 'px';
                pointer.style.setProperty('--width', rect.width + window.innerWidth / 50 + 'px');
        }else{
                pointer.style.setProperty('--height', rect.height + window.innerWidth / 50 + 'px');
            curW = 40;
             };
            curH = 40;
            smoothX += (mx - smoothX) * ease;
             smoothY += (my - smoothY) * ease;


             ptr.style.left = (smoothX - 20) + 'px';
             const onMouseLeave = function() {
            ptr.style.top = (smoothY - 20) + 'px';
                currentTarget = null;
            ptr.style.width = curW + 'px';
                pointer.style.setProperty('--width', '4rem');
            ptr.style.height = curH + 'px';
                pointer.style.setProperty('--height', '4rem');
        }
            };
        requestAnimationFrame(loop);
    }
    loop();


    // 保留你所有自定义按钮 + commentstreams + citizen原生
            // 自动绑定:你自定义的 + Citizen + 评论插件
    const sel = [
            const bindTargets = function() {
        '.citizen-nav a',
                document.querySelectorAll(`
        '.citizen-menu a',
                    ._target,
        '.citizen-button',
                    .citizen-button,
        '.citizen-action-button',
                    .citizen-nav a,
        '.cdx-button',
                    .citizen-menu a,
        '.mw-editsection a',
                    .citizen-sidebar a,
        '#citizen-header__nav a',
                    .cdx-button,
        '.citizen-sidebar a',
                    .mw-ui-button,
        '._target',
                    button,
        '.commentstreams-button',
                    [class*="commentstreams"] button,
        '.commentstreams-submit',
                    .commentstreams-box button,
        '.commentstreams-header button',
                    .commentstreams-submit
        '.commentstreams-box button',
                `).forEach(el => {
        '.mw-ui-button',
                    if (el._magneticBound) return;
        'button',
                    el._magneticBound = true;
        'a[role="button"]'
                    el.addEventListener('mouseenter', onMouseEnter);
    ].join(',');
                    el.addEventListener('mouseleave', onMouseLeave);
                });
            };


    function bind(){
            window.addEventListener('mousemove', onMouseMove);
        document.querySelectorAll(sel).forEach(el=>{
             bindTargets();
             if(el._magBind)return;
             const observer = new MutationObserver(bindTargets);
             el._magBind = 1;
             observer.observe(document.body, { childList: true, subtree: true });
            el.addEventListener('mouseenter', ()=> hoverEl = el);
             el.addEventListener('mouseleave', ()=> hoverEl = null);
         });
         });
     }
     });
 
    bind();
    new MutationObserver(bind).observe(document.body,{childList:true,subtree:true});
});
})();
})();

2026年3月31日 (二) 16:11的版本

(function() {
    mw.loader.using('jquery', function() {
        $(function() {
            if (document.querySelector('.magnetic-pointer-original')) return;

            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: 4rem;
    --height: 4rem;
    position: fixed;
    top: calc(var(--height) / -2);
    left: calc(var(--width) / -2);
    width: var(--width);
    height: var(--height);
    transition: all 0.2s ease-out;
    pointer-events: none;
    z-index: 99999;
}
/* 白天模式:绿色 */
.magnetic-pointer-original div {
    position: absolute;
    width: 0.8rem;
    height: 0.8rem;
    border-color: #17f700;
    background: transparent !important;
    border-top:3px solid transparent;
    border-left:3px solid transparent;
}
/* 黑夜模式:白色 */
html[data-color-scheme="dark"] .magnetic-pointer-original div {
    border-color: #ffffff !important;
}

.magnetic-pointer-original div:nth-child(1) {top:0;left:0;border-top-color:inherit;border-left-color:inherit;}
.magnetic-pointer-original div:nth-child(2) {top:0;right:0;border-top-color:inherit;border-right-color:inherit;}
.magnetic-pointer-original div:nth-child(3) {bottom:0;left:0;border-bottom-color:inherit;border-left-color:inherit;}
.magnetic-pointer-original div:nth-child(4) {bottom:0;right:0;border-bottom-color:inherit;border-right-color:inherit;}
            `;
            document.head.appendChild(style);

            let currentTarget = null;
            let currentX = 0, currentY = 0;

            const onMouseMove = function(e) {
                let x = e.clientX;
                let y = e.clientY;
                if (currentTarget) {
                    const rect = currentTarget.getBoundingClientRect();
                    const centerX = rect.left + rect.width / 2;
                    const centerY = rect.top + rect.height / 2;
                    x = centerX + (x - centerX) * 0.1;
                    y = centerY + (y - centerY) * 0.1;
                }
                currentX = x;
                currentY = y;
                pointer.style.transform = `translate(${currentX}px, ${currentY}px)`;
            };

            const onMouseEnter = function(e) {
                currentTarget = e.currentTarget;
                const rect = currentTarget.getBoundingClientRect();
                pointer.style.setProperty('--width', rect.width + window.innerWidth / 50 + 'px');
                pointer.style.setProperty('--height', rect.height + window.innerWidth / 50 + 'px');
            };

            const onMouseLeave = function() {
                currentTarget = null;
                pointer.style.setProperty('--width', '4rem');
                pointer.style.setProperty('--height', '4rem');
            };

            // 自动绑定:你自定义的 + Citizen + 评论插件
            const bindTargets = function() {
                document.querySelectorAll(`
                    ._target,
                    .citizen-button,
                    .citizen-nav a,
                    .citizen-menu a,
                    .citizen-sidebar a,
                    .cdx-button,
                    .mw-ui-button,
                    button,
                    [class*="commentstreams"] button,
                    .commentstreams-box button,
                    .commentstreams-submit
                `).forEach(el => {
                    if (el._magneticBound) return;
                    el._magneticBound = true;
                    el.addEventListener('mouseenter', onMouseEnter);
                    el.addEventListener('mouseleave', onMouseLeave);
                });
            };

            window.addEventListener('mousemove', onMouseMove);
            bindTargets();
            const observer = new MutationObserver(bindTargets);
            observer.observe(document.body, { childList: true, subtree: true });
        });
    });
})();