Mac-style Overlay Cursor (CSS Arrow, iPad/Desktop)

Overlay a Mac-style cursor (black fill, white border) that follows the real cursor and hides the system cursor. Works on iPadOS Safari (Userscripts) and desktop browsers.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Mac-style Overlay Cursor (CSS Arrow, iPad/Desktop)
// @namespace    https://greasyfork.org/en/users/000000
// @version      1.0
// @description  Overlay a Mac-style cursor (black fill, white border) that follows the real cursor and hides the system cursor. Works on iPadOS Safari (Userscripts) and desktop browsers.
// @author       NotNightmare
// @match        *://*/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Approx size of the arrow in your image
    const CURSOR_SIZE = 28; // tweak if you want it a bit bigger/smaller

    // Prevent double-injection
    if (window.__macCursorOverlayActive) return;
    window.__macCursorOverlayActive = true;

    // Inject styles
    const style = document.createElement('style');
    style.textContent = `
        html, body {
            cursor: none !important;
        }

        .mac-cursor-overlay {
            position: fixed;
            width: ${CURSOR_SIZE}px;
            height: ${CURSOR_SIZE}px;
            pointer-events: none;
            z-index: 999999;
            /* Adjust so the tip of the arrow sits on the real pointer */
            transform: translate(-3px, -2px);
        }

        /* Base arrow shape: black fill using CSS borders */
        .mac-cursor-shape {
            position: absolute;
            width: 0;
            height: 0;
            border-style: solid;
            border-width: ${CURSOR_SIZE}px 0 0 ${CURSOR_SIZE}px;
            border-color: transparent transparent transparent black;
        }

        /* White outline using a slightly bigger arrow behind (like a border) */
        .mac-cursor-outline {
            position: absolute;
            width: 0;
            height: 0;
            border-style: solid;
            border-width: ${CURSOR_SIZE + 2}px 0 0 ${CURSOR_SIZE + 2}px;
            border-color: transparent transparent transparent white;
            /* Put it behind the black arrow */
            left: -1px;
            top: -1px;
        }

        /* Soft drop shadow under the whole cursor */
        .mac-cursor-overlay {
            filter:
                drop-shadow(2px 2px 1px rgba(0,0,0,0.45));
        }
    `;
    document.documentElement.appendChild(style);

    // Build cursor DOM
    const cursor = document.createElement('div');
    cursor.className = 'mac-cursor-overlay';

    const outline = document.createElement('div');
    outline.className = 'mac-cursor-outline';

    const arrow = document.createElement('div');
    arrow.className = 'mac-cursor-shape';

    cursor.appendChild(outline);
    cursor.appendChild(arrow);
    document.documentElement.appendChild(cursor);

    // Position logic
    let x = window.innerWidth / 2;
    let y = window.innerHeight / 2;
    let raf = null;

    function update() {
        cursor.style.left = x + 'px';
        cursor.style.top = y + 'px';
        raf = null;
    }

    function move(e) {
        // Ignore pure touch gestures; we only want mouse/pencil/trackpad style pointers
        if (e.pointerType === 'touch') return;
        x = e.clientX;
        y = e.clientY;
        if (!raf) raf = requestAnimationFrame(update);
    }

    window.addEventListener('pointermove', move, { passive: true });
    window.addEventListener('mousemove', move, { passive: true });
})();