Show lyrics LT

Show lyrics on Lyricstraining

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Show lyrics LT
// @namespace    http://tampermonkey.net/
// @version      2025-01-04
// @description  Show lyrics on Lyricstraining
// @author       Valerio Valletta
// @match        https://lyricstraining.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=lyricstraining.com
// @grant        none
// ==/UserScript==

var autoScroll = true;

function setCookie(name, value, days) {
  var expires = "";
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
    expires = "; expires=" + date.toUTCString();
  }
  document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(";");
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == " ") c = c.substring(1, c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
  }
  return null;
}

function dragElement(elmnt) {
  var pos1 = 0,
    pos2 = 0,
    pos3 = 0,
    pos4 = 0;

  const oldBoxPos = getCookie("lyrics-box-pos");
  if (oldBoxPos) {
    const { top, left } = JSON.parse(oldBoxPos);

    elmnt.style.top = top;
    elmnt.style.left = left;
  }

  if (document.getElementById(elmnt.id + "-header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "-header").onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = elmnt.offsetTop - pos2 + "px";
    elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
  }

  function closeDragElement() {
    // stop moving when mouse button is released:
    const lyricsBox = document.querySelector("#lyrics-box");
    const lastBoxPos = {
      top: lyricsBox.style.top,
      left: lyricsBox.style.left,
    };

    setCookie("lyrics-box-pos", JSON.stringify(lastBoxPos));
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

function scrollParentToChild(parent, child) {
  // Where is the parent on page
  var parentRect = parent.getBoundingClientRect();
  // What can you see?
  var parentViewableArea = {
    height: parent.clientHeight,
    width: parent.clientWidth,
  };

  // Where is the child
  var childRect = child.getBoundingClientRect();

  // Calculate the child's center relative to the parent's center
  var childCenterY = childRect.top + childRect.height / 2;
  var parentCenterY = parentRect.top + parentViewableArea.height / 2;

  // Calculate the distance to scroll
  var scrollY = childCenterY - parentCenterY;

  // Adjust the parent's scroll position
  parent.scrollTop += scrollY;
}

const createLyricsBox = () => {
  const lyricsBox = document.createElement("div");

  lyricsBox.id = "lyrics-box";
  lyricsBox.style.display = "none";
  lyricsBox.style.zIndex = 50;
  lyricsBox.style.position = "absolute";
  lyricsBox.style.right = 0;
  lyricsBox.style.bottom = 10;
  lyricsBox.style.width = "100%";
  lyricsBox.style.height = "100%";
  lyricsBox.style.maxHeight = "300px";
  lyricsBox.style.maxWidth = "700px";
  lyricsBox.style.overflowY = "scroll";
  lyricsBox.style.backgroundColor = "#FFF";
  lyricsBox.style.boxShadow = "rgba(0, 0, 0, 0.24) 0px 3px 8px";

  lyricsBox.appendChild(createLyricsBoxHeader());
  return lyricsBox;
};
function createCheckbox() {
  // Create the input element
  const input = document.createElement("input");

  // Set attributes
  input.type = "checkbox";
  input.id = "switch-autoscroll";
  input.style.transform = "scale(1.5)";
  input.checked = true;
  input.onclick = toggleAutoScroll;

  return input;
}

const toggleAutoScroll = () => {
  autoScroll = !autoScroll;
  document.querySelector("#switch-autoscroll").checked = autoScroll;
};

const createSwitchAutoScroll = () => {
  const div = document.createElement("div");
  div.style.display = "flex";
  div.style.justifyContent = "center";
  div.style.alignItems = "center";
  div.style.padding = "0.5em";

  const text = document.createElement("span");
  text.innerText = "autoscroll";
  text.style.fontSize = "1.3em";
  text.style.color = "white";
  text.style.paddingRight = "0.3em";

  const checkbox = createCheckbox();

  div.append(text);
  div.appendChild(checkbox);

  return div;
};

const createLyricsBoxHeader = () => {
  const header = document.createElement("div");

  header.id = "lyrics-box-header";
  header.style.top = 0;
  header.style.position = "sticky";
  header.style.width = "100%";
  header.style.height = "100%";
  header.style.maxHeight = "50px";
  header.style.backgroundColor = "royalblue";
  header.style.cursor = "move";
  header.style.display = "flex";
  header.style.alignItems = "center";
  header.style.justifyContent = "space-between";

  const title = document.createElement("span");
  title.innerText = "DRAG ME";
  title.style.fontSize = "1.6em";
  title.style.color = "white";

  title.style.fontWeight = "bold";
  title.style.letterSpacing = "0.3em";
  title.style.padding = "0.5em";

  const switchAutoScroll = createSwitchAutoScroll();
  header.appendChild(title);
  header.appendChild(switchAutoScroll);
  return header;
};

const createShowLyricsBtn = () => {
  const btn = document.createElement("button");
  btn.id = "show-lyrics-btn";
  btn.innerText = "SHOW LYRICS";
  btn.style.fontSize = "1.5em";
  btn.style.fontWeight = "bold";
  btn.style.zIndex = 100;
  btn.style.position = "fixed";
  btn.style.right = 0;
  btn.style.bottom = 10;
  btn.style.border = "2px solid royalblue";
  btn.style.borderRight = "0px";
  btn.style.color = "royalblue";
  btn.style.background = "white";
  btn.style.cursor = "pointer";
  btn.style.transition = "0.5s all";

  return btn;
};

(function () {
  "use strict";

  const addOptions = document.querySelector("#add-options");

  const lyricsBox = createLyricsBox();

  lt.game.page.lyrics.lines
    .map((el) => el.text)
    .forEach((el, i) => {
      const p = document.createElement("p");
      p.className = "lyric-line";
      p.id = `line-${i}`;
      p.style.fontSize = "1.5em";
      p.style.color = "white";
      p.style.paddingLeft = "1em";
      p.innerText = el;
      lyricsBox.appendChild(p);
    });

  const btn = createShowLyricsBtn();

  btn.addEventListener("mouseenter", () => {
    let btn = document.querySelector("#show-lyrics-btn");

    btn.style.fontSize = "1.6em";
  });

  btn.addEventListener("mouseleave", () => {
    let btn = document.querySelector("#show-lyrics-btn");

    btn.style.fontSize = "1.5em";
  });

  btn.addEventListener("click", () => {
    let currStatus = document.querySelector("#lyrics-box").style.display;
    if (currStatus === "none") {
      document.querySelector("#lyrics-box").style.display = "block";
      return;
    }
    document.querySelector("#lyrics-box").style.display = "none";
    return;
  });

  addOptions.appendChild(btn);
  addOptions.appendChild(lyricsBox);

  dragElement(lyricsBox);

  var trackLineVisible = new Set();
  setInterval(() => {
    if (trackLineVisible) [hideVisibleLines()];

    const lineEls = document.querySelectorAll(".lyric-line");
    const currEl = lineEls[lt.game.page.playView.playLine];

    if (!lineEls || !currEl) return;

    currEl.style.color = "green";
    currEl.style.display = "block";
    if (autoScroll) {
      scrollParentToChild(lyricsBox, currEl);
    }
    trackLineVisible.add(currEl);
  }, 500);

  const hideVisibleLines = () => {
    trackLineVisible.forEach((el) => {
      el.style.color = "black";
    });

    trackLineVisible.clear();
  };
})();