// ==UserScript== // @name 设备模拟器 // @namespace http://tampermonkey.net/ // @version 1.2 // @description 模拟各种设备的 UA 和屏幕参数 // @author Your name // @license MIT // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM.setValue // @grant GM.getValue // @run-at document-start // @downloadURL none // ==/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 = `
设备模拟器
`; 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 }); // 修改屏幕参数 const screenProperties = { width: settings.width || window.innerWidth, height: settings.height || window.innerHeight, availWidth: settings.width || window.innerWidth, availHeight: settings.height || window.innerHeight }; // 修改 window 属性 Object.defineProperties(window, { 'innerWidth': { get: function() { return screenProperties.width; }, configurable: true }, 'innerHeight': { get: function() { return screenProperties.height; }, configurable: true }, 'outerWidth': { get: function() { return screenProperties.width; }, configurable: true }, 'outerHeight': { get: function() { return screenProperties.height; }, configurable: true }, 'devicePixelRatio': { get: function() { return settings.deviceScaleFactor || window.devicePixelRatio; }, configurable: true } }); // 修改 screen 属性 Object.defineProperties(screen, { 'width': { get: function() { return screenProperties.width; }, configurable: true }, 'height': { get: function() { return screenProperties.height; }, configurable: true }, 'availWidth': { get: function() { return screenProperties.availWidth; }, configurable: true }, 'availHeight': { get: function() { return screenProperties.availHeight; }, configurable: true } }); // 修改 visualViewport 属性(如果存在) if (window.visualViewport) { Object.defineProperties(window.visualViewport, { 'width': { get: function() { return screenProperties.width; }, configurable: true }, 'height': { get: function() { return screenProperties.height; }, configurable: true }, 'scale': { get: function() { return settings.deviceScaleFactor || 1; }, configurable: true } }); } // 触发各种可能的重绘事件 const events = ['resize', 'orientationchange']; events.forEach(eventName => { window.dispatchEvent(new Event(eventName)); }); // 如果页面有 CSS 媒体查询,可能需要强制重新计算样式 document.documentElement.style.zoom = '99.99999%'; setTimeout(() => { document.documentElement.style.zoom = '100%'; }, 10); } catch (e) { console.error('应用设置失败:', e); } } // 初始化 const container = createFloatingWindow(); initializeDrag(container); initializeEvents(container); // 默认收起状态 container.querySelector('#simulator-content').style.display = 'none'; container.querySelector('#toggle-simulator').textContent = '展开'; })();