光标替换实现

ixprism 发布于 3 天前 50 次阅读


给本站换了一个光标

CSS

/* 隐藏光标 */
html, body,
a, button, input, textarea,
[role="button"], [type="button"], [type="submit"] {
    cursor: none !important;
}

/* 公共样式:自定义光标层 */
.custom-cursor-dot,
.custom-cursor-ring {
    position: fixed;
    left: 0;
    top: 0;
    pointer-events: none;
    z-index: 99999;
    mix-blend-mode: difference; /* 灰色 + difference -> 伪自适应背景明暗 */
}

/* 内圆:鼠标本体,实心 */
.custom-cursor-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #bfbfbf;
    transform: translate3d(-50%, -50%, 0);
    transition: none !important; /* 防止主题乱加 transition: all */
}

/* 外圆:实心半透明圆盘 */
.custom-cursor-ring {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(191, 191, 191, 0.35);
    transform: translate3d(-50%, -50%, 0) scale(1);
    border: none;
    box-shadow: none;
    transition: transform 0.09s ease-out; /* 给按下缩放一个小动画 */
}

/* 鼠标按下时:外圆缩小到接近内圆大小 */
.custom-cursor-ring.is-pressed {
    /* 6 / 24 = 0.25,这里略大一点,看起来更自然 */
    transform: translate3d(-50%, -50%, 0) scale(0.32);
}

<script>
document.addEventListener("DOMContentLoaded", function () {
    const dot  = document.createElement("div");
    const ring = document.createElement("div");

    dot.className  = "custom-cursor-dot";
    ring.className = "custom-cursor-ring";

    document.body.appendChild(dot);
    document.body.appendChild(ring);

    // 鼠标目标位置
    let mouseX = window.innerWidth / 2;
    let mouseY = window.innerHeight / 2;

    // 外圆当前位置(用于拖尾插值)
    let ringX = mouseX;
    let ringY = mouseY;

    // 内圆
    document.addEventListener("mousemove", function (e) {
        mouseX = e.clientX;
        mouseY = e.clientY;

        dot.style.left = mouseX + "px";
        dot.style.top  = mouseY + "px";
    });

    // 外圆:轻微拖尾(但不被甩太远)
    function animate() {
        const ease   = 0.45;  // 越大越跟手
        const maxLag = 6;     // 最大允许落后距离

        const dx = mouseX - ringX;
        const dy = mouseY - ringY;
        const dist = Math.hypot(dx, dy);

        if (dist > maxLag) {
            // 太远时,强制把外圆拉回离鼠标 maxLag 的距离
            const ratio = maxLag / dist;
            ringX = mouseX - dx * ratio;
            ringY = mouseY - dy * ratio;
        } else {
            // 小范围内用缓动
            ringX += dx * ease;
            ringY += dy * ease;
        }

        ring.style.left = ringX + "px";
        ring.style.top  = ringY + "px";

        requestAnimationFrame(animate);
    }
    animate();

    // 鼠标按下时:外圆缩小;松开时恢复
    document.addEventListener("mousedown", function () {
        ring.classList.add("is-pressed");
    });

    document.addEventListener("mouseup", function () {
        ring.classList.remove("is-pressed");
    });

    // 防止鼠标按住移出页面导致状态卡住
    document.addEventListener("mouseleave", function () {
        ring.classList.remove("is-pressed");
        dot.style.opacity  = "0";
        ring.style.opacity = "0";
    });

    document.addEventListener("mouseenter", function () {
        dot.style.opacity  = "1";
        ring.style.opacity = "1";
    });

    // 触摸设备禁用自定义光标
    if ("ontouchstart" in window || navigator.maxTouchPoints > 0) {
        dot.style.display  = "none";
        ring.style.display = "none";
        document.documentElement.style.cursor = "auto";
        document.body.style.cursor = "auto";
    }
});
</script>

待解决:在部分设备上存在较高鼠标延迟

此作者没有提供个人介绍。
最后更新于 2025-11-19