设备模拟器

模拟各种设备的 UA 和屏幕参数

目前为 2024-12-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         设备模拟器
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  模拟各种设备的 UA 和屏幕参数
// @author       Your name
// @license      MIT
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM.setValue
// @grant        GM.getValue
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    
    // 预设设备列表
    const presetDevices = {
        'iPhone 13': {
            userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
            width: 390,
            height: 844,
            deviceScaleFactor: 3
        },
        'Pixel 5': {
            userAgent: 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36',
            width: 393,
            height: 851,
            deviceScaleFactor: 2.75
        },
        'iPad Pro': {
            userAgent: 'Mozilla/5.0 (iPad; CPU OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
            width: 1024,
            height: 1366,
            deviceScaleFactor: 2
        }
    };

    // 创建悬浮窗
    function createFloatingWindow() {
        const container = document.createElement('div');
        container.innerHTML = `
            <div id="device-simulator" style="position: fixed; top: 20px; right: 20px; background: white; border: 1px solid #ccc; padding: 10px; z-index: 9999; box-shadow: 0 0 10px rgba(0,0,0,0.1); min-width: 200px;">
                <div id="simulator-header" style="cursor: move; padding: 5px; background: #f0f0f0; margin-bottom: 10px;">
                    <span>设备模拟器</span>
                    <button id="toggle-simulator" style="float: right;">收起</button>
                </div>
                <div id="simulator-content">
                    <select id="device-select" style="width: 100%; margin-bottom: 10px;">
                        <option value="">选择设备</option>
                        ${Object.keys(presetDevices).map(device => `<option value="${device}">${device}</option>`).join('')}
                    </select>
                    <div style="margin-bottom: 10px;">
                        <label>User Agent:</label>
                        <textarea id="ua-input" style="width: 100%; height: 60px;"></textarea>
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label>屏幕宽度:</label>
                        <input type="number" id="width-input" style="width: 100%;">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label>屏幕高度:</label>
                        <input type="number" id="height-input" style="width: 100%;">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label>设备像素比:</label>
                        <input type="number" id="scale-input" style="width: 100%;" step="0.01">
                    </div>
                    <button id="apply-settings" style="width: 100%;">应用设置</button>
                </div>
            </div>
        `;

        document.body.appendChild(container);
        return container;
    }

    // 初始化拖拽功能
    function initializeDrag(container) {
        const header = container.querySelector('#simulator-header');
        let isDragging = false;
        let currentX;
        let currentY;
        let initialX;
        let initialY;

        header.addEventListener('mousedown', (e) => {
            isDragging = true;
            initialX = e.clientX - container.offsetLeft;
            initialY = e.clientY - container.offsetTop;
        });

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                currentX = e.clientX - initialX;
                currentY = e.clientY - initialY;
                container.style.left = currentX + 'px';
                container.style.top = currentY + 'px';
            }
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
        });
    }

    // 初始化事件监听
    function initializeEvents(container) {
        const toggleBtn = container.querySelector('#toggle-simulator');
        const content = container.querySelector('#simulator-content');
        const deviceSelect = container.querySelector('#device-select');
        const uaInput = container.querySelector('#ua-input');
        const widthInput = container.querySelector('#width-input');
        const heightInput = container.querySelector('#height-input');
        const scaleInput = container.querySelector('#scale-input');
        const applyBtn = container.querySelector('#apply-settings');

        // 加载保存的设置
        const savedSettings = GM_getValue('deviceSettings', null);
        if (savedSettings) {
            try {
                const settings = JSON.parse(savedSettings);
                uaInput.value = settings.userAgent || '';
                widthInput.value = settings.width || '';
                heightInput.value = settings.height || '';
                scaleInput.value = settings.deviceScaleFactor || '';
                // 立即应用保存的设置
                applySettings(settings);
            } catch (e) {
                console.error('加载设置失败:', e);
            }
        }

        // 切换显示/隐藏
        toggleBtn.addEventListener('click', () => {
            if (content.style.display === 'none') {
                content.style.display = 'block';
                toggleBtn.textContent = '收起';
            } else {
                content.style.display = 'none';
                toggleBtn.textContent = '展开';
            }
        });

        // 选择预设设备
        deviceSelect.addEventListener('change', () => {
            const device = presetDevices[deviceSelect.value];
            if (device) {
                uaInput.value = device.userAgent;
                widthInput.value = device.width;
                heightInput.value = device.height;
                scaleInput.value = device.deviceScaleFactor;
            }
        });

        // 应用设置
        applyBtn.addEventListener('click', () => {
            const settings = {
                userAgent: uaInput.value,
                width: parseInt(widthInput.value) || window.innerWidth,
                height: parseInt(heightInput.value) || window.innerHeight,
                deviceScaleFactor: parseFloat(scaleInput.value) || window.devicePixelRatio
            };
            
            try {
                GM_setValue('deviceSettings', JSON.stringify(settings));
                applySettings(settings);
                console.log('设置已保存');
            } catch (e) {
                console.error('保存设置失败:', e);
            }
        });
    }

    // 应用设备设置
    function applySettings(settings) {
        try {
            // 修改 User Agent
            Object.defineProperty(navigator, 'userAgent', {
                get: function() {
                    return settings.userAgent || navigator.userAgent;
                },
                configurable: true
            });

            // 修改屏幕参数
            Object.defineProperty(window, 'innerWidth', {
                get: function() {
                    return settings.width || window.innerWidth;
                },
                configurable: true
            });

            Object.defineProperty(window, 'innerHeight', {
                get: function() {
                    return settings.height || window.innerHeight;
                },
                configurable: true
            });

            Object.defineProperty(window, 'devicePixelRatio', {
                get: function() {
                    return settings.deviceScaleFactor || window.devicePixelRatio;
                },
                configurable: true
            });

            // 触发 resize 事件
            window.dispatchEvent(new Event('resize'));
        } catch (e) {
            console.error('应用设置失败:', e);
        }
    }

    // 初始化
    const container = createFloatingWindow();
    initializeDrag(container);
    initializeEvents(container);
    
    // 默认收起状态
    container.querySelector('#simulator-content').style.display = 'none';
    container.querySelector('#toggle-simulator').textContent = '展开';
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址