AniGamer Screenshot Helper

AniGamer Screenshot Tool – supports hotkey capture, burst mode, customizable hotkeys, burst interval settings, and menu language switch between Chinese and English.

Εγκατάσταση αυτού του κώδικαΒοήθεια
Κώδικας προτεινόμενος από τον δημιιουργό

Μπορεί, επίσης, να σας αρέσει ο κώδικας New Bahamut Cleaner & Content Widening.

Εγκατάσταση αυτού του κώδικα
// ==UserScript==
// @name         AniGamer Screenshot Helper
// @name:zh-TW   動畫瘋截圖助手
// @name:zh-CN   动画疯截图助手
// @namespace    https://www.tampermonkey.net/
// @version      2.0
// @description  AniGamer Screenshot Tool – supports hotkey capture, burst mode, customizable hotkeys, burst interval settings, and menu language switch between Chinese and English.
// @description:zh-TW 動畫瘋截圖工具,支援快捷鍵截圖、連拍模式,自定義快捷鍵、連拍間隔設定、中英菜單切換
// @description:zh-CN 动画疯截图工具,支援快捷键截图、连拍模式,自定义快捷键、连拍间隔设定、中英菜单切换
// @author       ChatGPT
// @match        https://ani.gamer.com.tw/*
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  // 預設快捷鍵
  const DEFAULT_SHORTCUT = 'S';
  // 預設連拍間隔(毫秒)
  const DEFAULT_INTERVAL = 1000;
  // 最小連拍間隔(毫秒)
  const MIN_INTERVAL = 100;

  // 多語系字典
  const i18n = {
    EN: {
      langSwitch: 'LANG EN',
      setKey: key => `Set Shortcut Key (Current: ${key})`,
      setInterval: ms => `Set Burst Interval (Current: ${ms}ms)`,
      inputKey: 'Enter a new shortcut key (one character):',
      inputInterval: 'Enter new burst interval in ms (min: 100):',
      invalidInterval: 'Invalid input. Must be ≥ 100.'
    },
    ZH: {
      langSwitch: '語言 中文',
      setKey: key => `設定快捷鍵(目前:${key})`,
      setInterval: ms => `設定連拍間隔(目前:${ms}ms)`,
      inputKey: '請輸入新的截圖快捷鍵(單一字母):',
      inputInterval: '請輸入新的連拍間隔(單位:毫秒,最小值:100):',
      invalidInterval: '請輸入一個不小於 100 的有效數字。'
    }
  };

  // 取得目前設定(語言、快捷鍵、連拍間隔)
  function getSettings() {
    return {
      lang: GM_getValue('lang', 'EN'),
      shortcutKey: GM_getValue('screenshotKey', DEFAULT_SHORTCUT),
      interval: parseInt(GM_getValue('burstInterval', DEFAULT_INTERVAL), 10)
    };
  }

  // 產生檔名:影片標題_小時_分鐘_秒_毫秒_解析度.png
  function generateFilename(video, canvas) {
    // 補零用
    const pad = (n, len = 2) => n.toString().padStart(len, '0');
    const time = video.currentTime;
    const h = pad(Math.floor(time / 3600));
    const m = pad(Math.floor((time % 3600) / 60));
    const s = pad(Math.floor(time % 60));
    const ms = pad(Math.floor((time % 1) * 1000), 3);
    // 取得網頁標題並移除非法字元
    const rawTitle = document.title;
    const cleanedTitle = rawTitle.replace(/[\s\\/:*?"<>|]/g, '_');
    // 解析度
    const resolution = `${canvas.width}x${canvas.height}`;
    // 修改命名規則:影片標題_小時_分鐘_秒_毫秒_解析度
    return `${cleanedTitle}_${h}_${m}_${s}_${ms}_${resolution}.png`;
  }

  // 截圖主程式
  function captureScreenshot() {
    const video = document.querySelector('video');
    // 若找不到影片或影片未載入完成則不執行
    if (!video || video.readyState < 2) return;

    // 建立 canvas 並繪製當前影像
    const canvas = document.createElement('canvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

    // 產生檔名
    const filename = generateFilename(video, canvas);

    // 轉成 blob 並觸發下載
    canvas.toBlob(blob => {
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = filename;
      a.click();
      // 延遲釋放 blob,避免尚未下載即釋放
      setTimeout(() => URL.revokeObjectURL(a.href), 1000);
    }, 'image/png');
  }

  // 綁定快捷鍵與連拍事件
  (function bindHotkeys() {
    let isPressing = false;   // 是否正在按壓
    let burstTimer = null;    // 連拍計時器

    window.addEventListener('keydown', e => {
      const { shortcutKey, interval } = getSettings();
      // 按下自訂快捷鍵且未重複觸發時
      if (e.key.toUpperCase() === shortcutKey.toUpperCase() && !isPressing) {
        isPressing = true;
        captureScreenshot();
        burstTimer = setInterval(captureScreenshot, interval);
      }
    });

    window.addEventListener('keyup', e => {
      const { shortcutKey } = getSettings();
      // 放開自訂快捷鍵時停止連拍
      if (e.key.toUpperCase() === shortcutKey.toUpperCase()) {
        isPressing = false;
        if (burstTimer) clearInterval(burstTimer);
      }
    });
  })();

  // 註冊油猴右上角選單
  (function registerMenu() {
    // 動態取得目前語系與設定
    function t() {
      const { lang, shortcutKey, interval } = getSettings();
      return { ...i18n[lang], shortcutKey, interval, lang };
    }

    // 設定快捷鍵
    GM_registerMenuCommand(t().setKey(t().shortcutKey), () => {
      const input = prompt(t().inputKey, t().shortcutKey);
      // 僅接受單一字元
      if (input && input.length === 1) {
        GM_setValue('screenshotKey', input.toUpperCase());
        location.reload(); // 直接重新整理,不跳提示
      }
    });

    // 設定連拍間隔
    GM_registerMenuCommand(t().setInterval(t().interval), () => {
      const input = prompt(t().inputInterval, t().interval);
      const newVal = parseInt(input, 10);
      if (!isNaN(newVal) && newVal >= MIN_INTERVAL) {
        GM_setValue('burstInterval', newVal);
        location.reload(); // 直接重新整理,不跳提示
      } else {
        alert(t().invalidInterval); // 僅錯誤時提示
      }
    });

    // 語言切換
    GM_registerMenuCommand(t().langSwitch, () => {
      const newLang = t().lang === 'EN' ? 'ZH' : 'EN';
      GM_setValue('lang', newLang);
      location.reload();
    });
  })();

})();