打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

杂物间:空山新雨后.js

来自EaseCation Wiki
// 杂物间:空山新雨后.js - 全屏修复完整版
(function() {
    'use strict';

    // ★★★ 修复1:页面名称必须带下划线(空格会被替换为 _ ) ★★★
    var pageName = mw.config.get('wgPageName');
    if (pageName !== '杂物间:空山新雨后') return;

    $(function() {
        var $container = $('.miss-you-container');
        var $overlay = $container.find('.miss-you-overlay');
        var $final = $container.find('.miss-you-final');
        var $blackout = $container.find('.miss-you-blackout');

        if (!$overlay.length) return;

        var isFlooding = false;
        var isFinished = false;
        var currentSpeed = 600;
        var speedLevel = 0;
        var addInterval = null;
        var speedTimer = null;
        var batchFastInterval = null;
        var coverCheckInterval = null;

        function getBounds() {
            var rect = $overlay[0].getBoundingClientRect();
            return { width: rect.width, height: rect.height };
        }

        function addMissWord() {
            if (isFinished) return;
            var bounds = getBounds();
            if (bounds.width <= 0 || bounds.height <= 0) return;

            var word = document.createElement('div');
            word.className = 'miss-word';
            word.textContent = '我想你';

            var rand = Math.random();
            var fontSize;
            if (rand < 0.5) fontSize = 12 + Math.random() * 20;
            else if (rand < 0.8) fontSize = 32 + Math.random() * 40;
            else fontSize = 72 + Math.random() * 58;
            word.style.fontSize = fontSize + 'px';

            var left = Math.random() * (bounds.width - Math.min(150, bounds.width - 10));
            var top = Math.random() * (bounds.height - 50);
            word.style.left = left + 'px';
            word.style.top = top + 'px';
            word.style.color = '#000000';
            word.style.opacity = '0';

            $overlay[0].appendChild(word);
            setTimeout(function() {
                if (word.parentNode) word.style.opacity = '0.85';
            }, 5);

            if ($overlay[0].children.length > 1500) {
                var toRemove = $overlay[0].children.length - 1200;
                for (var i = 0; i < toRemove; i++) {
                    if ($overlay[0].children[i]) $overlay[0].children[i].remove();
                }
            }
        }

        function addBatch(count) {
            for (var i = 0; i < count; i++) {
                (function(idx) {
                    setTimeout(function() { addMissWord(); }, idx * 15);
                })(i);
            }
        }

        function checkCoverageAndFinish() {
            if (isFinished || !isFlooding) return;
            var count = $overlay[0].children.length;
            if (count >= 600 || (currentSpeed <= 30 && count >= 350)) {
                finishAndBlackout();
            }
        }

        // ★★★ 修复2:终局时把遮罩和红字移到 <body> 下,确保全屏覆盖 ★★★
        function finishAndBlackout() {
            if (isFinished) return;
            isFinished = true;
            isFlooding = false;

            clearInterval(addInterval);
            clearInterval(coverCheckInterval);
            clearInterval(speedTimer);
            if (batchFastInterval) clearInterval(batchFastInterval);

            for (var i = 0; i < 100; i++) {
                (function(idx) {
                    setTimeout(function() { addMissWord(); }, idx * 8);
                })(i);
            }

            // === 核心修复:将遮罩和红字移动到 <body> 下 ===
            var blackoutEl = $blackout[0];
            var finalEl = $final[0];
            if (blackoutEl && blackoutEl.parentNode) {
                document.body.appendChild(blackoutEl);
            }
            if (finalEl && finalEl.parentNode) {
                document.body.appendChild(finalEl);
            }

            // 重新获取引用(DOM 移动后 jQuery 对象依然有效)
            setTimeout(function() {
                $blackout.addClass('show');
            }, 10);

            setTimeout(function() {
                $final.addClass('show');
            }, 800);

            // 保险:2 秒后强制显示
            setTimeout(function() {
                if (!$blackout.hasClass('show')) {
                    $blackout.addClass('show');
                }
            }, 2000);
        }

        function increaseSpeed() {
            if (!isFlooding || isFinished) return;
            speedLevel++;
            if (speedLevel <= 20) currentSpeed = Math.max(25, currentSpeed * 0.85);
            else if (speedLevel <= 40) currentSpeed = Math.max(12, currentSpeed * 0.92);
            else currentSpeed = Math.max(6, currentSpeed * 0.95);

            clearInterval(addInterval);
            addInterval = setInterval(function() {
                if (isFlooding && !isFinished) {
                    addMissWord();
                    if (Math.random() < 0.25) setTimeout(function() { addMissWord(); }, 8);
                }
            }, currentSpeed);

            if (currentSpeed < 40 && isFlooding && !isFinished) {
                if (batchFastInterval) clearInterval(batchFastInterval);
                batchFastInterval = setInterval(function() {
                    if (isFlooding && !isFinished) {
                        for (var i = 0; i < 4; i++) {
                            (function(idx) {
                                setTimeout(function() { addMissWord(); }, idx * 10);
                            })(i);
                        }
                    }
                }, 1200);
            }
        }

        function startFlooding() {
            if (isFlooding || isFinished) return;
            isFlooding = true;
            addBatch(25);

            currentSpeed = 550;
            addInterval = setInterval(function() {
                if (isFlooding && !isFinished) {
                    addMissWord();
                    if (Math.random() < 0.2) setTimeout(function() { addMissWord(); }, 8);
                }
            }, currentSpeed);

            speedTimer = setInterval(function() {
                if (isFlooding && !isFinished) increaseSpeed();
                else clearInterval(speedTimer);
            }, 1000);

            coverCheckInterval = setInterval(function() {
                checkCoverageAndFinish();
            }, 300);
        }

        setTimeout(function() {
            if (!isFlooding && !isFinished) startFlooding();
        }, 1000);

        console.log('[空山新雨后] 蔓延效果已初始化 (全屏修复版)');
    });
})();