// ==UserScript== // @name GoodNote - 网页笔记助手 // @namespace http://tampermonkey.net/ // @version 0.2 // @description 在任何网页添加笔记功能 // @author kasusa // @license MIT // @match *://*/* // @grant none // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 创建样式 const style = document.createElement('style'); style.textContent = ` .note-icon { position: fixed; top: 20px; right: 20px; width: 40px; height: 40px; background-color: #4CAF50; border-radius: 50%; cursor: move; z-index: 9999; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: all 0.3s ease; user-select: none; will-change: transform; transform: translate3d(0, 0, 0); } .note-icon:hover { transform: scale(1.1); } .note-icon svg { width: 24px; height: 24px; fill: white; } .note-container { position: fixed; background: ; backdrop-filter: blur(10px); border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); z-index: 9998; padding: 10px; transition: all 0.3s ease; opacity: 0; transform: scale(0); transform-origin: center; min-width: 350px; } .note-container.active { opacity: 1; transform: scale(1); } .note-textarea { width: 92%; min-height: 250px; border: 1px solid #ddd; border-radius: 4px; padding: 12px; font-size: 14px; resize: all; font-family: Arial, sans-serif; line-height: 1.5; } .note-textarea:focus { outline: none; border-color: #4CAF50; } `; document.head.appendChild(style); // 创建笔记图标 const noteIcon = document.createElement('div'); noteIcon.className = 'note-icon'; noteIcon.innerHTML = ` `; // 创建笔记容器 const noteContainer = document.createElement('div'); noteContainer.className = 'note-container'; // 创建文本框 const textarea = document.createElement('textarea'); textarea.className = 'note-textarea'; textarea.placeholder = '在这里输入你的笔记...'; noteContainer.appendChild(textarea); // 添加到页面 document.body.appendChild(noteIcon); document.body.appendChild(noteContainer); // 获取当前域名作为存储键 const storageKey = `goodnote_${window.location.hostname}`; const positionKey = `goodnote_position_${window.location.hostname}`; // 从localStorage加载笔记 const savedNote = localStorage.getItem(storageKey); if (savedNote) { textarea.value = savedNote; } // 实现拖拽功能 let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; let rafId = null; noteIcon.addEventListener('mousedown', dragStart); document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd); function dragStart(e) { if (e.target === noteIcon || noteIcon.contains(e.target)) { isDragging = true; const rect = noteIcon.getBoundingClientRect(); initialX = e.clientX - rect.left; initialY = e.clientY - rect.top; noteIcon.style.transition = 'none'; } } function drag(e) { if (isDragging) { e.preventDefault(); if (rafId) { cancelAnimationFrame(rafId); } rafId = requestAnimationFrame(() => { const newX = e.clientX - initialX; const newY = e.clientY - initialY; currentX = Math.min(Math.max(0, newX), window.innerWidth - noteIcon.offsetWidth); currentY = Math.min(Math.max(0, newY), window.innerHeight - noteIcon.offsetHeight); setTranslate(currentX, currentY); }); } } function setTranslate(xPos, yPos) { noteIcon.style.left = `${xPos}px`; noteIcon.style.top = `${yPos}px`; noteIcon.style.right = 'auto'; noteIcon.style.bottom = 'auto'; } function dragEnd(e) { if (isDragging) { isDragging = false; noteIcon.style.transition = 'all 0.1s ease'; localStorage.setItem(positionKey, JSON.stringify({ top: noteIcon.style.top, left: noteIcon.style.left })); if (rafId) { cancelAnimationFrame(rafId); } } } // 加载保存的位置 const savedPosition = localStorage.getItem(positionKey); if (savedPosition) { try { const { top, left } = JSON.parse(savedPosition); setTranslate(parseInt(left), parseInt(top)); } catch (e) { console.error('Failed to load saved position'); } } // 修改笔记显示逻辑 noteContainer.style.position = 'fixed'; let isVisible = false; noteIcon.addEventListener('click', (e) => { if (!isDragging) { isVisible = !isVisible; if (isVisible) { const iconRect = noteIcon.getBoundingClientRect(); const windowWidth = window.innerWidth; let left = iconRect.right - 10; if (left + 400 > windowWidth) { left = iconRect.left - 360; } noteContainer.style.top = `${iconRect.top}px`; noteContainer.style.left = `${left}px`; noteContainer.style.display = 'block'; requestAnimationFrame(() => { noteContainer.classList.add('active'); }); } else { noteContainer.classList.remove('active'); setTimeout(() => { noteContainer.style.display = 'none'; }, 300); } } }); // 修改点击其他地方关闭笔记的逻辑 document.addEventListener('click', (e) => { if (!noteContainer.contains(e.target) && !noteIcon.contains(e.target) && isVisible) { isVisible = false; noteContainer.classList.remove('active'); setTimeout(() => { noteContainer.style.display = 'none'; }, 300); } }); // 自动保存功能 let saveTimeout; textarea.addEventListener('input', () => { clearTimeout(saveTimeout); saveTimeout = setTimeout(() => { localStorage.setItem(storageKey, textarea.value); }, 500); // 延迟500ms保存,避免频繁保存 }); })();