Skip to content

Instantly share code, notes, and snippets.

@Recursing
Created April 29, 2023 17:56
Show Gist options
  • Save Recursing/94f577bcbc99c154303febc2f4984138 to your computer and use it in GitHub Desktop.
Save Recursing/94f577bcbc99c154303febc2f4984138 to your computer and use it in GitHub Desktop.
function getSelectedText() {
return window.getSelection().toString();
}
let restartTimeout = null;
function restartPeriodically() {
window.speechSynthesis.pause();
window.speechSynthesis.resume();
restartTimeout = setTimeout(restartPeriodically, 5000);
}
function stop() {
window.clearTimeout(restartTimeout);
window.speechSynthesis.cancel();
}
function speak(text) {
stop();
if (!text) {
alert("Select some text first");
return;
}
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = "en";
utterance.rate = rate.value;
utterance.voice = window.speechSynthesis
.getVoices()
.filter((v) => v.lang == "en-US")[0];
utterance.onend = () => {
window.clearTimeout(restartTimeout);
};
speechSynthesis.speak(utterance);
restartPeriodically();
}
const overlay = document.createElement("div");
overlay.setAttribute(
"style",
`
box-sizing: border-box;
font-family: "Inter", sans-serif;
position: fixed;
z-index: 999999;
top: 10px;
left: 50%;
border: 1px solid red;
border-radius: 10px;
padding: 4px;
background-color: orange;
cursor: move;
`
);
const startBtn = document.createElement("button");
startBtn.innerText = "Speak";
const btnStyle = `
margin: 4px;
box-shadow: inset 0px 1px 0px 0px #ffffff;
background: linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
background-color: #ffffff;
border-radius: 6px;
border: 1px solid #dcdcdc;
display: inline-block;
color: black;
padding: 2px 8px;
text-decoration: none;
text-shadow: 0px 1px 0px #ffffff;
`;
startBtn.setAttribute("style", btnStyle);
startBtn.addEventListener("click", () => {
speak(getSelectedText());
});
const stopBtn = document.createElement("button");
stopBtn.innerText = "Stop";
stopBtn.addEventListener("click", () => {
stop();
});
stopBtn.setAttribute("style", btnStyle);
const rate = document.createElement("input");
rate.type = "range";
rate.min = 0.5;
rate.max = 2;
rate.step = 0.05;
rate.value = 1.55;
rate.setAttribute("style", `display: block`);
overlay.appendChild(rate);
overlay.appendChild(startBtn);
overlay.appendChild(stopBtn);
let lastX, lastY;
overlay.addEventListener("mousedown", function (event) {
lastX = event.clientX;
lastY = event.clientY;
overlay.style.cursor = "grabbing";
});
overlay.addEventListener("mousemove", function (event) {
if (overlay.style.cursor !== "grabbing") return;
event.preventDefault();
let offsetX = event.clientX - lastX;
let offsetY = event.clientY - lastY;
overlay.style.top = overlay.offsetTop + offsetY + "px";
overlay.style.left = overlay.offsetLeft + offsetX + "px";
lastX = event.clientX;
lastY = event.clientY;
});
overlay.addEventListener("mouseup", function () {
overlay.style.cursor = "move";
});
document.body.appendChild(overlay);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment