Equestria Daily Slideshow

Create a fullscreen slideshow for Equestria Daily Drawfriend posts

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Equestria Daily Slideshow
// @namespace    http://tampermonkey.net/
// @version      0.1
// @license      MPL v2.0
// @description  Create a fullscreen slideshow for Equestria Daily Drawfriend posts
// @author       Medo
// @match        https://www.equestriadaily.com/*
// @grant        GM_addStyle
// ==/UserScript==
(function() {
    'use strict';

    if (!document.querySelector('.post-body img')) return;

    GM_addStyle(`
        .slideshow-container {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000000;
            overflow: hidden;
        }

        .image-set {
            position: absolute;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 1;
            z-index: 10;
        }

        .image-set.hiddenses {
            opacity: 0;
            filter: blur(200px);
            z-index: 11;
        }

        .image-layer {
            position: absolute;
        }

        .image-layer img {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }

        .overlay {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: none;
            justify-content: center;
            align-items: center;
            background-color: rgba(0, 0, 0, 0.5);
            z-index: 20;
        }

        .overlay-message {
            color: white;
            font-size: 2rem;
            text-shadow: 2px 2px black;
            white-space: nowrap;
        }
    `);

    const images = Array.from(document.querySelectorAll('.post-body img'))
        .map(img => img.src)
        .filter(src => /\.(jpg|jpeg|png|gif)$/i.test(src));

    let currentIndex = 0;
    let slideshowContainer;
    let previousImageSet, activeImageSet, nextImageSet;

    function createSlideshow() {
        slideshowContainer = document.createElement('div');
        slideshowContainer.className = 'slideshow-container';

        previousImageSet = createImageSet('image-set hiddenses');
        activeImageSet = createImageSet('image-set');
        nextImageSet = createImageSet('image-set hiddenses');

        prepareSet(previousImageSet, images.length-1);
        prepareSet(activeImageSet, 0);
        prepareSet(nextImageSet, 1 % images.length);

        slideshowContainer.appendChild(previousImageSet);
        slideshowContainer.appendChild(activeImageSet);
        slideshowContainer.appendChild(nextImageSet);

        document.body.appendChild(slideshowContainer);
    }

    function createImageSet(classNames) {
        var imageSet = document.createElement('div');
        imageSet.className = classNames;

        for (let i = 7; i >= -7; i-=2) {
            createLayer(imageSet, Math.pow(1.7, i) / 20, Math.pow(2, i) / 30);
        }

        createLayer(imageSet, 0, 0);

        // Add overlay for wrap-around message
	    const overlay = document.createElement('div');
	    overlay.className = 'overlay';
	    imageSet.appendChild(overlay);

        return imageSet;
    }

    function createLayer(imageSet, blurscale, scale) {
        const layer = document.createElement('div');
        layer.className = 'image-layer';
        layer.style.filter = `blur(calc(min(${blurscale * 50}vh, ${blurscale * 50}vw)))`;
        layer.style.width = `${100 * scale + 100}vw`;
        layer.style.height = `${100 * scale + 100}vh`;

        const img = document.createElement('img');
        layer.appendChild(img);

        imageSet.appendChild(layer);
    }

    function switchImageSets(direction) {
        activeImageSet.style.transition='opacity 0.7s, filter 0.7s ease-in';
        activeImageSet.classList.add('hiddenses');
        activeImageSet.style.zIndex=11;

        if (direction === 'forward') {
            [previousImageSet, activeImageSet, nextImageSet] = [activeImageSet, nextImageSet, previousImageSet];
            const newIndex = (currentIndex + 1) % images.length;
            prepareSet(nextImageSet, newIndex);
            if (newIndex === 0) {
                nextImageSet.querySelector('.overlay').style.display = 'flex';
                nextImageSet.querySelector('.overlay').innerHTML = '<div class="overlay-message">This is the first image!</div>';
            }
            nextImageSet.style.zIndex=9;
        } else {
            [previousImageSet, activeImageSet, nextImageSet] = [nextImageSet, previousImageSet, activeImageSet];
            prepareSet(previousImageSet, (currentIndex - 1 + images.length) % images.length);
            previousImageSet.style.zIndex=9;
        }

        activeImageSet.style.transition='filter 0.7s ease';
        activeImageSet.classList.remove('hiddenses');
        activeImageSet.style.zIndex=10;
    }

    function prepareSet(imageSet, imageIndex) {
        const layers = imageSet.querySelectorAll('.image-layer img');
        layers.forEach((img) => {
            img.src = images[imageIndex];
        });
        imageSet.querySelector('.overlay').style.display = 'none';
    }

    function nextImage() {
        currentIndex = (currentIndex + 1) % images.length;
        switchImageSets('forward');
    }

    function previousImage() {
        currentIndex = (currentIndex - 1 + images.length) % images.length;
        switchImageSets('backwards');
    }

    function closeSlideshow() {
        slideshowContainer.style.transition = 'opacity 0.5s';
        slideshowContainer.style.opacity = '0';
        document.querySelector("html").style.overflow="";
        document.removeEventListener('keydown', handleKeydown);
        setTimeout(() => {
            document.body.removeChild(slideshowContainer);
        }, 500);
    }

    function handleKeydown(event) {
        if (event.key === 'ArrowRight') {
            nextImage();
        } else if (event.key === 'ArrowLeft') {
            previousImage();
        } else if (event.key === 'Escape') {
            closeSlideshow();
        }
    }

    function runScript() {
        createSlideshow();
        document.querySelector("html").style.overflow="hidden";
        document.addEventListener('keydown', handleKeydown);
    }

    // Function to create and insert the button
    function addButton() {
        const button = document.createElement('button');
        button.textContent = 'Slideshow';
        button.style.position = 'fixed';
        button.style.top = '10px';
        button.style.right = '10px';
        button.style.zIndex = '9999';
        button.addEventListener('click', runScript);
        document.body.appendChild(button);
    }

    // Add the button to the webpage
    addButton();
})();