Greasy Fork

Greasy Fork is available in English.

LinkedIn Learning 字幕大小调整

在 LinkedIn Learning 视频播放器设置菜单中添加字幕大小调整功能

目前为 2024-11-16 提交的版本。查看 最新版本

// ==UserScript==
// @name         LinkedIn Learning 字幕大小调整
// @name:en      LinkedIn Learning Subtitle Size Adjuster
// @name:zh-CN   LinkedIn Learning 字幕大小调整
// @name:zh-TW   LinkedIn Learning 字幕大小調整
// @name:ja      LinkedIn Learning 字幕サイズ調整
// @name:ko      LinkedIn Learning 자막 크기 조정
// @name:es      Ajustador de tamaño de subtítulos de LinkedIn Learning
// @name:fr      Ajusteur de taille des sous-titres LinkedIn Learning
// @name:it      Regolatore dimensione sottotitoli LinkedIn Learning
// @name:de      LinkedIn Learning Untertitelgrößen-Anpasser
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description         在 LinkedIn Learning 视频播放器设置菜单中添加字幕大小调整功能
// @description:en      Add subtitle size adjustment to LinkedIn Learning video player settings
// @description:zh-CN   在 LinkedIn Learning 视频播放器设置菜单中添加字幕大小调整功能
// @description:zh-TW   在 LinkedIn Learning 視頻播放器設置菜單中添加字幕大小調整功能
// @description:ja      LinkedIn Learning のビデオプレーヤー設定に字幕サイズ調整機能を追加
// @description:ko      LinkedIn Learning 비디오 플레이어 설정에 자막 크기 조정 기능 추가
// @description:es      Agregar ajuste de tamaño de subtítulos en la configuración del reproductor de LinkedIn Learning
// @description:fr      Ajouter le réglage de la taille des sous-titres dans les paramètres du lecteur LinkedIn Learning
// @description:it      Aggiunge la regolazione della dimensione dei sottotitoli nelle impostazioni del player LinkedIn Learning
// @description:de      Fügt Untertitelgrößenanpassung zu den LinkedIn Learning Player-Einstellungen hinzu
// @author      经本正一
// @license     MIT
// @match       https://www.linkedin.com/learning/*
// @grant       none
// ==/UserScript==

(function() {
    'use strict';

    const DEFAULT_FONT_SIZE = 16;
    const STORAGE_KEY = 'linkedin_learning_subtitle_size';

    function getSavedFontSize() {
        return localStorage.getItem(STORAGE_KEY) || DEFAULT_FONT_SIZE;
    }

    function saveFontSize(size) {
        localStorage.setItem(STORAGE_KEY, size);
    }

    // 创建字幕设置菜单
    function createSubtitleMenu() {
        const menuHtml = `
            <div class="vjs-menu-item subtitle-size-control" role="menuitem" tabindex="-1">
                <span>字幕大小</span>
                <div style="margin-top: 5px;">
                    <button class="vjs-menu-button" id="increase-subtitle" style="margin-right: 5px;">放大</button>
                    <button class="vjs-menu-button" id="decrease-subtitle" style="margin-right: 5px;">缩小</button>
                    <button class="vjs-menu-button" id="reset-subtitle">默认</button>
                </div>
            </div>
        `;

        // 等待设置菜单加载
        const settingsButton = document.querySelector('.vjs-settings-menu');
        if (!settingsButton) return;

        const menuItems = settingsButton.querySelector('.vjs-menu-content');
        if (!menuItems) return;

        // 创建新的菜单项
        const subtitleControl = document.createElement('div');
        subtitleControl.innerHTML = menuHtml;

        // 插入到第一个位置
        if (menuItems.firstChild) {
            menuItems.insertBefore(subtitleControl.firstElementChild, menuItems.firstChild);
        } else {
            menuItems.appendChild(subtitleControl.firstElementChild);
        }

        // 添加样式
        const style = document.createElement('style');
        style.textContent = `
            .subtitle-size-control {
                padding: 8px 12px !important;
                text-align: center !important;
            }
            .subtitle-size-control button {
                background: transparent;
                border: 1px solid #fff;
                color: #fff;
                padding: 2px 8px;
                border-radius: 3px;
                cursor: pointer;
                font-size: 12px;
            }
            .subtitle-size-control button:hover {
                background: rgba(255,255,255,0.2);
            }
        `;
        document.head.appendChild(style);
    }

    function applySubtitleStyle() {
        const fontSize = getSavedFontSize();
        const style = document.createElement('style');
        style.textContent = `
            .vjs-text-track-cue,
            .vjs-text-track-display div,
            .captions-display span,
            .vjs-text-track-display > div > div > div {
                font-size: ${fontSize}px !important;
                line-height: ${Number(fontSize) + 8}px !important;
            }
        `;

        const oldStyle = document.getElementById('subtitle-style');
        if (oldStyle) {
            oldStyle.remove();
        }

        style.id = 'subtitle-style';
        document.head.appendChild(style);
    }

    function adjustSubtitleSize(increase, reset = false) {
        let newSize;
        const currentSize = Number(getSavedFontSize());

        if (reset) {
            newSize = DEFAULT_FONT_SIZE;
        } else {
            newSize = increase ? currentSize + 2 : currentSize - 2;
        }

        saveFontSize(newSize);
        applySubtitleStyle();
    }

    function addListeners() {
        document.getElementById('increase-subtitle')?.addEventListener('click', (e) => {
            e.stopPropagation();
            adjustSubtitleSize(true);
        });
        document.getElementById('decrease-subtitle')?.addEventListener('click', (e) => {
            e.stopPropagation();
            adjustSubtitleSize(false);
        });
        document.getElementById('reset-subtitle')?.addEventListener('click', (e) => {
            e.stopPropagation();
            adjustSubtitleSize(false, true);
        });
    }

    function observeDOM() {
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                // 检查设置菜单是否已加载
                if (!document.querySelector('.subtitle-size-control')) {
                    createSubtitleMenu();
                    addListeners();
                }
                // 应用字幕样式
                const subtitleElements = document.querySelectorAll('.vjs-text-track-cue, .captions-display');
                if (subtitleElements.length > 0) {
                    applySubtitleStyle();
                }
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    function init() {
        createSubtitleMenu();
        addListeners();
        applySubtitleStyle();
        observeDOM();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();