Twitch Stream Zoom and Pan

Zoom in, zoom out, and pan on Twitch streams using keyboard controls

// ==UserScript==
// @name         Twitch Stream Zoom and Pan
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Zoom in, zoom out, and pan on Twitch streams using keyboard controls
// @author       Guile93
// @match        *://*.twitch.tv/*
// @icon         https://www.example.com/icon.png
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let zoomLevel = 1;
    const minZoom = 1;
    const maxZoom = 3;
    const zoomStep = 0.1;
    let panX = 0;
    let panY = 0;
    const panStep = 20;

    function updateTransform() {
        const video = document.querySelector('video');
        if (video) {
            video.style.transform = `scale(${zoomLevel}) translate(${panX / zoomLevel}px, ${panY / zoomLevel}px)`;
            video.style.transformOrigin = 'center center';
        }
    }

    // Create zoom controls
    const zoomControls = document.createElement('div');
    zoomControls.style.position = 'fixed';
    zoomControls.style.bottom = '10px';
    zoomControls.style.left = '10px';
    zoomControls.style.zIndex = '1000';
    zoomControls.style.backgroundColor = '#333';
    zoomControls.style.color = '#fff';
    zoomControls.style.border = '1px solid #444';
    zoomControls.style.padding = '5px';
    zoomControls.style.borderRadius = '5px';
    zoomControls.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
    zoomControls.innerHTML = `
      <button id="zoomIn" style="background-color: #555; color: #fff; border: none; padding: 5px 10px; margin: 2px; border-radius: 3px;">[+]</button>
      <button id="zoomOut" style="background-color: #555; color: #fff; border: none; padding: 5px 10px; margin: 2px; border-radius: 3px;">[-]</button>
      <button id="resetZoom" style="background-color: #555; color: #fff; border: none; padding: 5px 10px; margin: 2px; border-radius: 3px;">[R]</button>
    `;
    document.body.appendChild(zoomControls);

    document.getElementById('zoomIn').addEventListener('click', () => {
        zoomLevel = Math.min(maxZoom, zoomLevel + zoomStep);
        updateTransform();
    });

    document.getElementById('zoomOut').addEventListener('click', () => {
        zoomLevel = Math.max(minZoom, zoomLevel - zoomStep);
        updateTransform();
    });

    document.getElementById('resetZoom').addEventListener('click', () => {
        zoomLevel = 1;
        panX = 0;
        panY = 0;
        updateTransform();
    });

    // Add keyboard controls for panning
    document.addEventListener('keydown', (e) => {
        if (zoomLevel > 1) {
            switch (e.key) {
                case 'ArrowUp':
                    panY -= panStep;
                    updateTransform();
                    break;
                case 'ArrowDown':
                    panY += panStep;
                    updateTransform();
                    break;
                case 'ArrowLeft':
                    panX -= panStep;
                    updateTransform();
                    break;
                case 'ArrowRight':
                    panX += panStep;
                    updateTransform();
                    break;
            }
        }
        switch (e.key) {
            case '+':
            case '=':
                zoomLevel = Math.min(maxZoom, zoomLevel + zoomStep);
                updateTransform();
                break;
            case '-':
                zoomLevel = Math.max(minZoom, zoomLevel - zoomStep);
                updateTransform();
                break;
            case '0':
                zoomLevel = 1;
                panX = 0;
                panY = 0;
                updateTransform();
                break;
        }
    });

    // Initial setup
    const video = document.querySelector('video');
    if (video) {
        video.style.cursor = 'grab';
    }
    updateTransform();
})();