Enlarge YouTube Profile Pictures (HD Version with Caching)

Enlarges YouTube profile pictures on mouse over, shows HD version, Caches HD images for faster display using Tampermonkey caching.

目前為 2024-11-05 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Enlarge YouTube Profile Pictures (HD Version with Caching)
// @namespace    https://github.com/Nick2bad4u/UserStyles
// @version      3.1
// @description  Enlarges YouTube profile pictures on mouse over, shows HD version, Caches HD images for faster display using Tampermonkey caching.
// @author       Nick2bad4u
// @match        https://www.youtube.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @license      UnLicense
// ==/UserScript==

(function () {
  "use strict";

  let debounceTimeout;
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
  const preloadedImages = new Map();

  // Load cache from Tampermonkey storage
  function loadCache() {
    const cache = GM_getValue("profilePicCache", {});
    const now = Date.now();
    // Clear out expired cache entries
    Object.keys(cache).forEach((key) => {
      if (now - cache[key].timestamp > CACHE_TTL_MS) {
        delete cache[key]; // Remove expired entry
      }
    });
    GM_setValue("profilePicCache", cache); // Update cache after removing expired entries
    return cache;
  }

  // Save cache to Tampermonkey storage
  function saveCache(cache) {
    GM_setValue("profilePicCache", cache);
  }

  let cache = loadCache(); // Load the cache once when the script runs

  // Preload HD image
  function preloadHDImage(src) {
    const hdSrc = src.replace(/=s(32|88|48)-c/, "=s800-c"); // Adjust as needed for HD
    if (!preloadedImages.has(hdSrc)) {
      if (cache[hdSrc]) {
        // If in persistent cache, load directly from cache
        preloadedImages.set(hdSrc, cache[hdSrc].url);
      } else {
        // Preload HD image and store in cache
        const img = new Image();
        img.src = hdSrc;
        preloadedImages.set(hdSrc, hdSrc); // Store in memory
        cache[hdSrc] = {
          url: hdSrc,
          timestamp: Date.now(),
        }; // Cache with timestamp
        saveCache(cache); // Save the updated cache
      }
    }
  }

  // Function to enlarge profile pictures, show HD image, add black outline, and shift position
  function enlargeProfilePic(event) {
    clearTimeout(debounceTimeout);

    const img = event.target;

    // If the image is already enlarged, skip further processing
    if (img.dataset.enlarged === "true") return;

    debounceTimeout = setTimeout(() => {
      const originalSrc = img.src;
      const hdSrc = originalSrc.replace(/=s(32|88|48)-c/, "=s800-c"); // Increase the size to 800px
      img.dataset.originalSrc = originalSrc; // Store the original src
      img.src = preloadedImages.get(hdSrc) || hdSrc;

      // Get the position of the original image
      const rect = img.getBoundingClientRect();

      // Set fixed size, position relative to the original image
      if (img.classList.contains("h-5.w-5.inline.align-middle.rounded-full.flex-none")) {
        img.style.transform = "scale(6) translateX(20px)";
        img.style.transition = "transform 0.2s ease";
        img.style.border = "1px solid black";
        img.style.zIndex = "9999";
        img.style.position = "relative";
      } else {
        img.style.width = "260px"; // Adjust width as needed
        img.style.height = "260px"; // Adjust height as needed
        img.style.borderRadius = "50%"; // Make the image circular
        img.style.position = "fixed";
        img.style.top = `${rect.top - 20}px`; // Adjust vertical position as needed
        img.style.left = `${rect.left + 70}px`; // Offset to the right
        img.style.border = "2px solid black";
        img.style.zIndex = "9999";
      }

      img.dataset.enlarged = "true"; // Mark as enlarged to prevent re-enlarging

      // Reset after 3 seconds
      setTimeout(() => {
        resetProfilePic(img);
      }, 3000);
    }, 100);
  }

  // Function to reset profile pictures to original size and source
  function resetProfilePic(img) {
    img.src = img.dataset.originalSrc || img.src; // Restore the original src if it was replaced
    img.style.width = ""; // Clear custom width
    img.style.height = ""; // Clear custom height
    img.style.borderRadius = ""; // Clear circular style
    img.style.position = ""; // Reset position to default
    img.style.top = ""; // Clear top position
    img.style.left = ""; // Clear left position
    img.style.border = "none"; // Remove any border
    img.style.zIndex = "auto"; // Reset z-index
    img.style.transform = ""; // Remove any transform applied
    delete img.dataset.enlarged; // Remove the enlarged flag
  }

  // Add event listeners to profile pictures
  function addEventListeners() {
    const profilePicsChat = document.querySelectorAll(
      ".h-5.w-5.inline.align-middle.rounded-full.flex-none",
    );
    const profilePicsComments = document.querySelectorAll(
      ".style-scope yt-img-shadow img:not(#avatar-btn > yt-img-shadow img)",
    );

    profilePicsChat.forEach((pic) => {
      preloadHDImage(pic.src); // Preload HD image
      pic.addEventListener("mouseover", enlargeProfilePic);
    });

    profilePicsComments.forEach((pic) => {
      preloadHDImage(pic.src); // Preload HD image
      pic.addEventListener("mouseover", enlargeProfilePic);
    });
  }

  // Observe changes in the chat and comments section to dynamically add event listeners
  const observer = new MutationObserver(() => {
    addEventListeners();
  });
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });

  // Initial call to add event listeners
  addEventListeners();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址