您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhanced reading experience for local txt files with Element UI style and improved themes
- // ==UserScript==
- // @name Local TXT Reader
- // @namespace http://tampermonkey.net/
- // @version 1.5
- // @description Enhanced reading experience for local txt files with Element UI style and improved themes
- // @author JiuYou2020
- // @license MIT
- // @match file:///*
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- (function() {
- 'use strict';
- // Ensure the script runs only on .txt files
- if (window.location.pathname.endsWith('.txt')) {
- // Set up styles
- const style = document.createElement('style');
- style.innerHTML = `
- body {
- margin: 0;
- padding: 0;
- display: flex;
- height: 100vh;
- overflow: hidden;
- transition: background-color 0.3s, color 0.3s;
- background-size: cover;
- background-position: center;
- }
- .outer-container {
- flex: 1;
- overflow-y: auto;
- scroll-behavior: smooth;
- padding: 20px;
- }
- .content-container {
- width: 55%;
- margin: 0 auto;
- transition: font-size 0.3s, line-height 0.3s, background-color 0.3s, color 0.3s;
- padding: 20px;
- border-radius: 10px;
- }
- .content-container p {
- text-indent: 2em;
- margin-top: 1em;
- }
- #settingsBtn {
- position: fixed;
- right: 20px;
- bottom: 20px;
- z-index: 1000;
- padding: 12px;
- background-color: #409EFF;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- font-size: 16px;
- box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
- transition: background-color 0.3s;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- #settingsBtn:hover {
- background-color: #66b1ff;
- }
- #settingsPanel {
- display: none;
- position: fixed;
- right: 20px;
- bottom: 80px;
- background-color: white;
- border: 1px solid #EBEEF5;
- border-radius: 4px;
- padding: 20px;
- z-index: 1000;
- box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
- }
- #settingsPanel div {
- margin-bottom: 15px;
- }
- #settingsPanel button {
- margin-right: 5px;
- padding: 8px 15px;
- border: 1px solid #DCDFE6;
- border-radius: 4px;
- cursor: pointer;
- transition: all 0.3s;
- background-color: white;
- color: #606266;
- }
- #settingsPanel button:hover {
- color: #409EFF;
- border-color: #c6e2ff;
- background-color: #ecf5ff;
- }
- .theme-btn {
- width: 30px;
- height: 30px;
- border-radius: 4px;
- }
- #classicTheme { background-color: #e7e3d8; }
- #whiteTheme { background-color: #ffffff; border: 1px solid #DCDFE6 !important; }
- #darkTheme { background-color: #1e1e1e; }
- .font-btn, .line-height-btn {
- background-color: #409EFF !important;
- color: white !important;
- border: none !important;
- }
- .font-btn:hover, .line-height-btn:hover {
- background-color: #66b1ff !important;
- color: white !important;
- }
- #resetDefault {
- background-color: #F56C6C !important;
- color: white !important;
- border: none !important;
- }
- #resetDefault:hover {
- background-color: #f78989 !important;
- }
- #customBgInput {
- display: none;
- }
- #customBgLabel {
- display: inline-block;
- padding: 8px 15px;
- background-color: #67C23A;
- color: white;
- border-radius: 4px;
- cursor: pointer;
- transition: background-color 0.3s;
- }
- #customBgLabel:hover {
- background-color: #85ce61;
- }
- `;
- document.head.appendChild(style);
- // Get the text content
- const text = document.body.textContent.trim();
- // Split the text into paragraphs by newlines
- const paragraphs = text.split(/\n+/).map(paragraph => paragraph.trim());
- // Clear the body content
- document.body.innerHTML = '';
- // Create the outer container
- const outerContainer = document.createElement('div');
- outerContainer.className = 'outer-container';
- document.body.appendChild(outerContainer);
- // Create the content container
- const contentContainer = document.createElement('div');
- contentContainer.className = 'content-container';
- outerContainer.appendChild(contentContainer);
- // Add paragraphs to the content container
- paragraphs.forEach(paragraph => {
- if (paragraph) { // Only add non-empty paragraphs
- const p = document.createElement('p');
- p.textContent = paragraph;
- contentContainer.appendChild(p);
- }
- });
- // Create settings button
- const settingsBtn = document.createElement('button');
- settingsBtn.id = 'settingsBtn';
- settingsBtn.textContent = '设置';
- document.body.appendChild(settingsBtn);
- // Create settings panel
- const settingsPanel = document.createElement('div');
- settingsPanel.id = 'settingsPanel';
- settingsPanel.innerHTML = `
- <div>
- 大小:
- <button id="decreaseFont" class="font-btn">-</button>
- <span id="currentFontSize"></span>
- <button id="increaseFont" class="font-btn">+</button>
- </div>
- <div>
- 行高:
- <button id="decreaseLineHeight" class="line-height-btn">-</button>
- <span id="currentLineHeight"></span>
- <button id="increaseLineHeight" class="line-height-btn">+</button>
- </div>
- <div>
- 主题:
- <button id="classicTheme" class="theme-btn" title="经典"></button>
- <button id="whiteTheme" class="theme-btn" title="纯白"></button>
- <button id="darkTheme" class="theme-btn" title="暗黑"></button>
- </div>
- <div>
- <label for="customBgInput" id="customBgLabel">自定义背景</label>
- <input type="file" id="customBgInput" accept="image/*">
- </div>
- <div>
- <button id="resetDefault">恢复默认设置</button>
- </div>
- `;
- document.body.appendChild(settingsPanel);
- // Define themes
- const themes = {
- classic: { bg: '#e7e3d8', text: '#333333', contentBg: '#f1ede4' },
- white: { bg: '#ffffff', text: '#333333', contentBg: '#ffffff' },
- dark: { bg: '#1e1e1e', text: '#ffffff', contentBg: 'rgba(30, 30, 30, 0.8)' }
- };
- // Function to save settings
- function saveSettings() {
- const settings = {
- fontSize: contentContainer.style.fontSize,
- lineHeight: contentContainer.style.lineHeight,
- theme: currentTheme,
- customBg: document.body.style.backgroundImage,
- btnPosition: {
- right: settingsBtn.style.right,
- bottom: settingsBtn.style.bottom
- }
- };
- GM_setValue('readerSettings', JSON.stringify(settings));
- }
- // Function to load settings
- function loadSettings() {
- const savedSettings = GM_getValue('readerSettings', null);
- if (savedSettings) {
- const settings = JSON.parse(savedSettings);
- contentContainer.style.fontSize = settings.fontSize || '19px';
- contentContainer.style.lineHeight = settings.lineHeight || '1.5';
- applyTheme(settings.theme || 'classic');
- if (settings.customBg) {
- document.body.style.backgroundImage = settings.customBg;
- }
- if (settings.btnPosition) {
- settingsBtn.style.right = settings.btnPosition.right;
- settingsBtn.style.bottom = settings.btnPosition.bottom;
- }
- } else {
- resetToDefault();
- }
- }
- // Function to apply theme
- function applyTheme(theme) {
- if (theme !== 'custom') {
- document.body.style.backgroundColor = themes[theme].bg;
- document.body.style.color = themes[theme].text;
- contentContainer.style.backgroundColor = themes[theme].contentBg;
- document.body.style.backgroundImage = '';
- }
- currentTheme = theme;
- }
- // Function to reset to default settings
- function resetToDefault() {
- contentContainer.style.fontSize = '19px';
- contentContainer.style.lineHeight = '1.5';
- applyTheme('classic');
- document.body.style.backgroundImage = '';
- settingsBtn.style.right = '20px';
- settingsBtn.style.bottom = '20px';
- updateSettingsDisplay();
- saveSettings();
- }
- // Load settings
- let currentTheme = 'classic';
- loadSettings();
- // Function to save the current scroll position
- function saveScrollPosition() {
- const scrollPosition = outerContainer.scrollTop;
- const fileName = window.location.pathname.split('/').pop();
- GM_setValue(fileName, scrollPosition);
- }
- // Function to load the saved scroll position
- function loadScrollPosition() {
- const fileName = window.location.pathname.split('/').pop();
- const savedPosition = GM_getValue(fileName, 0);
- outerContainer.scrollTop = savedPosition;
- }
- // Load the saved position when the page loads
- loadScrollPosition();
- // Save the position when the user scrolls
- outerContainer.addEventListener('scroll', saveScrollPosition);
- // Handle arrow key navigation
- document.addEventListener('keydown', function(e) {
- const scrollAmount = 100; // Adjust this value to change scroll speed
- if (e.key === 'ArrowUp') {
- outerContainer.scrollBy({top: -scrollAmount, behavior: 'smooth'});
- e.preventDefault();
- } else if (e.key === 'ArrowDown') {
- outerContainer.scrollBy({top: scrollAmount, behavior: 'smooth'});
- e.preventDefault();
- }
- });
- // Toggle settings panel
- settingsBtn.addEventListener('click', () => {
- settingsPanel.style.display = settingsPanel.style.display === 'none' ? 'block' : 'none';
- updatePanelPosition();
- });
- // Make settings button draggable
- let isDragging = false;
- let dragOffsetX, dragOffsetY;
- settingsBtn.addEventListener('mousedown', (e) => {
- isDragging = true;
- dragOffsetX = e.clientX - settingsBtn.offsetLeft;
- dragOffsetY = e.clientY - settingsBtn.offsetTop;
- });
- document.addEventListener('mousemove', (e) => {
- if (isDragging) {
- const newX = e.clientX - dragOffsetX;
- const newY = e.clientY - dragOffsetY;
- settingsBtn.style.right = `${document.body.clientWidth - newX - settingsBtn.offsetWidth}px`;
- settingsBtn.style.bottom = `${document.body.clientHeight - newY - settingsBtn.offsetHeight}px`;
- updatePanelPosition();
- }
- });
- document.addEventListener('mouseup', () => {
- if (isDragging) {
- isDragging = false;
- saveSettings();
- }
- });
- // Update settings panel position
- function updatePanelPosition() {
- const btnRect = settingsBtn.getBoundingClientRect();
- settingsPanel.style.right = settingsBtn.style.right;
- settingsPanel.style.bottom = `${parseFloat(settingsBtn.style.bottom) + btnRect.height + 10}px`;
- }
- // Font size controls
- document.getElementById('decreaseFont').addEventListener('click', () => {
- const currentSize = parseInt(contentContainer.style.fontSize);
- if (currentSize > 10) {
- contentContainer.style.fontSize = (currentSize - 1) + 'px';
- updateSettingsDisplay();
- saveSettings();
- }
- });
- document.getElementById('increaseFont').addEventListener('click', () => {
- const currentSize = parseInt(contentContainer.style.fontSize);
- if (currentSize < 30) {
- contentContainer.style.fontSize = (currentSize + 1) + 'px';
- updateSettingsDisplay();
- saveSettings();
- }
- });
- // Line height controls
- document.getElementById('decreaseLineHeight').addEventListener('click', () => {
- const currentHeight = parseFloat(contentContainer.style.lineHeight);
- if (currentHeight > 1) {
- contentContainer.style.lineHeight = (currentHeight - 0.1).toFixed(1);
- updateSettingsDisplay();
- saveSettings();
- }
- });
- document.getElementById('increaseLineHeight').addEventListener('click', () => {
- const currentHeight = parseFloat(contentContainer.style.lineHeight);
- if (currentHeight < 3) {
- contentContainer.style.lineHeight = (currentHeight + 0.1).toFixed(1);
- updateSettingsDisplay();
- saveSettings();
- }
- });
- // Theme controls
- document.getElementById('classicTheme').addEventListener('click', () => {
- applyTheme('classic');
- saveSettings();
- });
- document.getElementById('whiteTheme').addEventListener('click', () => {
- applyTheme('white');
- saveSettings();
- });
- document.getElementById('darkTheme').addEventListener('click', () => {
- applyTheme('dark');
- saveSettings();
- });
- // Custom background
- document.getElementById('customBgInput').addEventListener('change', (e) => {
- const file = e.target.files[0];
- if (file) {
- const reader = new FileReader();
- reader.onload = function(e) {
- document.body.style.backgroundImage = `url(${e.target.result})`;
- currentTheme = 'custom';
- saveSettings();
- }
- reader.readAsDataURL(file);
- }
- });
- // Reset to default
- document.getElementById('resetDefault').addEventListener('click', resetToDefault);
- // Update display of current settings
- function updateSettingsDisplay() {
- document.getElementById('currentFontSize').textContent = contentContainer.style.fontSize;
- document.getElementById('currentLineHeight').textContent = contentContainer.style.lineHeight;
- }
- updateSettingsDisplay();
- }
- })();