您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Highlight text on any website and have it read using TTS with options for voice and speed.
// ==UserScript== // @name Text Highlighter with TTS // @namespace http://tampermonkey.net/ // @version 0.2 // @description Highlight text on any website and have it read using TTS with options for voice and speed. // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; // Create GUI let gui = document.createElement('div'); gui.style.position = 'fixed'; gui.style.top = '20px'; gui.style.left = '20px'; gui.style.width = '300px'; gui.style.height = '200px'; gui.style.background = 'gray'; gui.style.borderRadius = '10px'; gui.style.boxShadow = '2px 2px 10px rgba(0, 0, 0, 0.5)'; gui.innerHTML = ` <div style="background-color: #ccc; padding: 10px; border-radius: 10px 10px 0 0;"> <span style="font-size: 18px;">Highlighter</span> </div> <div style="padding: 10px;"> <button id="readButton">Read Selected Text</button> <br><br> <label for="voiceSelect">Voice: </label> <select id="voiceSelect"></select> <br><br> <label for="speedRange">Speed: </label> <input type="range" id="speedRange" min="0.5" max="2" step="0.1" value="1"> </div> `; document.body.appendChild(gui); // Drag functionality gui.onmousedown = function(e) { let shiftX = e.clientX - gui.getBoundingClientRect().left; let shiftY = e.clientY - gui.getBoundingClientRect().top; function moveAt(pageX, pageY) { gui.style.left = pageX - shiftX + 'px'; gui.style.top = pageY - shiftY + 'px'; } function onMouseMove(e) { moveAt(e.pageX, e.pageY); } document.addEventListener('mousemove', onMouseMove); gui.onmouseup = function() { document.removeEventListener('mousemove', onMouseMove); gui.onmouseup = null; }; }; gui.ontouchstart = function(e) { let shiftX = e.touches[0].clientX - gui.getBoundingClientRect().left; let shiftY = e.touches[0].clientY - gui.getBoundingClientRect().top; function moveAt(pageX, pageY) { gui.style.left = pageX - shiftX + 'px'; gui.style.top = pageY - shiftY + 'px'; } function onTouchMove(e) { moveAt(e.touches[0].pageX, e.touches[0].pageY); } document.addEventListener('touchmove', onTouchMove); gui.ontouchend = function() { document.removeEventListener('touchmove', onTouchMove); gui.ontouchend = null; }; }; // Disable text selection while dragging gui.ondragstart = function() { return false; }; // TTS setup let synth = window.speechSynthesis; let voices = []; function populateVoiceList() { voices = synth.getVoices(); let voiceSelect = document.getElementById('voiceSelect'); voiceSelect.innerHTML = ''; voices.forEach((voice, index) => { let option = document.createElement('option'); option.textContent = voice.name + ' (' + voice.lang + ')'; option.value = index; voiceSelect.appendChild(option); }); } populateVoiceList(); if (speechSynthesis.onvoiceschanged !== undefined) { speechSynthesis.onvoiceschanged = populateVoiceList; } // Detect selected text let selectedText = ''; document.addEventListener('selectionchange', () => { let selection = window.getSelection(); if (selection && selection.rangeCount > 0) { selectedText = selection.toString().trim(); } }); // Read selected text using TTS document.getElementById('readButton').addEventListener('click', () => { if (selectedText) { let utterThis = new SpeechSynthesisUtterance(selectedText); utterThis.voice = voices[document.getElementById('voiceSelect').value]; utterThis.rate = document.getElementById('speedRange').value; synth.speak(utterThis); } else { alert('Please select some text first.'); } }); })();