/** * YCat Editor - 文章阅读进度条 * 功能:实时显示当前阅读位置,点击进度条跳转到对应位置 * 作者:QClaw(自主开发) * 日期:2026-06-20 */ (function() { 'use strict'; // 进度条配置 const PROGRESS_CONFIG = { height: '4px', // 进度条高度 bgColor: '#e0e0e0', // 背景色 fillColor: 'var(--brand)', // 填充色(品牌 teal) zIndex: 50, // 层级(低于顶栏/弹窗) position: 'bottom', // 位置:top / bottom smooth: true, // 是否平滑动画 showPercentage: false // 是否显示百分比文字 }; // 创建进度条元素 function createProgressBar() { const progressBar = document.createElement('div'); progressBar.id = 'reading-progress-bar'; progressBar.style.cssText = ` position: fixed; ${PROGRESS_CONFIG.position}: 0; left: 0; width: 100%; height: ${PROGRESS_CONFIG.height}; background: ${PROGRESS_CONFIG.bgColor}; z-index: ${PROGRESS_CONFIG.zIndex}; cursor: pointer; `; const progressFill = document.createElement('div'); progressFill.id = 'reading-progress-fill'; progressFill.style.cssText = ` width: 0%; height: 100%; background: ${PROGRESS_CONFIG.fillColor}; ${PROGRESS_CONFIG.smooth ? 'transition: width 0.1s ease;' : ''} `; progressBar.appendChild(progressFill); // 点击进度条跳转 progressBar.addEventListener('click', function(e) { const rect = this.getBoundingClientRect(); const clickX = e.clientX - rect.left; const percentage = clickX / rect.width; const editorContent = document.querySelector('.w-e-text-container'); if (editorContent) { const scrollHeight = editorContent.scrollHeight - editorContent.clientHeight; editorContent.scrollTop = scrollHeight * percentage; } }); document.body.appendChild(progressBar); return progressFill; } // 更新进度条 function updateProgress() { let scrollTop = 0, scrollHeight = 0; const editorContent = document.querySelector('.w-e-text-container'); if (editorContent && (editorContent.scrollHeight - editorContent.clientHeight) > 0) { scrollTop = editorContent.scrollTop; scrollHeight = editorContent.scrollHeight - editorContent.clientHeight; } else { scrollTop = window.scrollY || document.documentElement.scrollTop; scrollHeight = (document.documentElement.scrollHeight - window.innerHeight); } const progress = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0; const fill = document.getElementById('reading-progress-fill'); if (fill) { fill.style.width = (Math.min(100, Math.max(0, progress))) + '%'; } } // 初始化 function initReadingProgress() { // 等待编辑器加载完成 const checkEditor = setInterval(() => { const editorContent = document.querySelector('.w-e-text-container'); if (editorContent) { clearInterval(checkEditor); // 创建进度条 createProgressBar(); // 监听滚动(编辑器内部 + 整页) editorContent.addEventListener('scroll', updateProgress); window.addEventListener('scroll', updateProgress, { passive: true }); // 监听编辑器内容变化(重新计算) const observer = new MutationObserver(updateProgress); observer.observe(editorContent, { childList: true, subtree: true }); console.log('[ReadingProgress] 初始化完成'); } }, 500); // 超时保护(5秒) setTimeout(() => clearInterval(checkEditor), 5000); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initReadingProgress); } else { initReadingProgress(); } })();