【油猴脚本】Linux.do论坛可以刷弹幕了!

看论坛是否感觉枯燥,是否感觉缺少氛围?

论坛弹幕来了,欢迎体验。

还不是很完善,有一些问题。
欢迎各位大佬帮忙修改。
我算抛砖引玉了。
欢迎点赞。

体验地址:

源码,欢迎魔改
// ==UserScript==
// @name         linux.do弹幕
// @namespace    linux.do弹幕氛围   
// @version      0.6.2
// @description  快来填满我吧
// @author       nulluser
// @match        https://linux.do/*
// @icon         https://linux.do/uploads/default/optimized/1X/3a18b4b0da3e8cf96f7eea15241c3d251f28a39b_2_180x180.png
// @grant        none
// @license      MIT
// @downloadURL https://update.greasyfork.org/scripts/490237/linuxdo%E5%BC%B9%E5%B9%95.user.js
// @updateURL https://update.greasyfork.org/scripts/490237/linuxdo%E5%BC%B9%E5%B9%95.meta.js
// ==/UserScript==

(function () {
    'use strict';

    // 创建弹幕容器
    const danmuContainer = document.createElement('div');
    danmuContainer.id = 'danmu-container';
    danmuContainer.style.position = 'fixed';
    danmuContainer.style.left = '0';
    danmuContainer.style.bottom = '0';
    danmuContainer.style.width = '260px'; // 容器宽度
    danmuContainer.style.height = '100%';
    danmuContainer.style.zIndex = '9999';
    danmuContainer.style.overflow = 'hidden';
    document.body.appendChild(danmuContainer);

    // 弹幕数组
    let danmus = [];

    // 添加弹幕
    function addDanmu(text) {
        const danmu = document.createElement('div');
        danmu.className = 'danmu';
        danmu.textContent = text;
        danmu.style.position = 'absolute';
        danmu.style.whiteSpace = 'nowrap';
        danmu.style.color = getRandomColor(); // 随机颜色
        danmu.style.fontSize = '20px';
        danmu.style.fontWeight = 'bold';
        danmu.style.left = getRandomPx();
        danmu.style.bottom = '0'; // 弹幕从底部进入
        danmu.style.writingMode = 'vertical-lr'; // 文字竖直显示
        danmu.style.transform = 'translateX(-100%)'; // 初始位置在容器外
        danmuContainer.appendChild(danmu);

        // 弹幕动画
        const pageHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
        const duration = Math.random() * (pageHeight * 10) + pageHeight * 15; // 随机动画持续时间,基于页面高度
        danmu.animate([
            { transform: `translateY(-${pageHeight}px)` } // 向上移动直到消失
        ], {
            duration: duration,
            iterations: 1,
            easing: 'linear'
        }).finished.then(() => danmu.remove());

        // 更新弹幕位置
        updateDanmuPositions();
    }

    // 更新弹幕位置,防止重叠
    function updateDanmuPositions() {
        let lastBottom = 0; // 初始化上一个弹幕的底部位置
        danmus.forEach(danmu => {
            danmu.style.bottom = `${lastBottom}px`;
            lastBottom = parseFloat(danmu.style.bottom) + danmu.offsetHeight + 20; // 更新下一个弹幕的位置
        });
    }

    // 生成随机颜色
    function getRandomColor() {
        const letters = '0123456789ABCDEF';
        let color = '#';
        for (let i = 0; i < 6; i++) {
            color += letters[Math.floor(Math.random() * 16)];
        }
        return color;
    }
    // 获取弹幕数据
function fetchDanmuData() {
    const currentUrl = window.location.href;
    const jsonUrl = currentUrl.endsWith('.json') ? currentUrl : currentUrl + '.json';
    fetch(jsonUrl)
        .then(response => response.json())
        .then(data => {
            if (data && data.post_stream && data.post_stream.posts) {
                const posts = data.post_stream.posts;
                let postIndex = 1; // 从第二条开始
                function addDanmuWithDelay() {
                    if (postIndex < posts.length) {
                        const post = posts[postIndex++];
                        const cookedContent = post.cooked.replace(/<[^>]*>?/gm, ''); // 移除HTML标签
                        addDanmu(cookedContent);
                        setTimeout(addDanmuWithDelay, 1000); // 每次添加后间隔0.2秒
                    }
                }
                addDanmuWithDelay(); // 开始添加弹幕
            }
        })
        .catch(error => {
            console.error('Error fetching danmu data:', error);
        });
}

// 假设 addDanmu 函数已经定义,它负责添加弹幕到页面上

    // 生成随机位置
    function getRandomPx() {
        const randomNumber = Math.floor(Math.random() * 10) + 1; // 生成1到5的随机数
        return randomNumber * 20 + 'px'; // 添加单位px并返回
    }



    // 每隔一段时间添加一个新的弹幕
    setInterval(() => {
        addDanmu('吾皇万岁!');
        addDanmu('欢迎来到Linux.do!');
        addDanmu('始皇牛牛牛!');
        addDanmu('快来填满我吧!');
        addDanmu('吾皇万睡!');
    }, 10000);
    fetchDanmuData();
setInterval(() => {fetchDanmuData(); }, 20000);

    function monitorTopicURLChange(callback) {
        const urlPattern = /^(https:\/\/linux\.do\/t\/topic\/\d+).*$/; // 正则表达式匹配基本URL
        let lastMatch = location.href.match(urlPattern);
        new MutationObserver(() => {
            const currentMatch = location.href.match(urlPattern);
            if (currentMatch && (!lastMatch || currentMatch[1] !== lastMatch[1])) {
                lastMatch = currentMatch;
                callback(currentMatch[1]);
            }
        }).observe(document, { subtree: true, childList: true });
    }

    // 使用示例
    monitorTopicURLChange(newBaseURL => {
        fetchDanmuData();
    });
    observer.observe(document.body, { childList: true, subtree: true });
    window.addEventListener('load', fetchDanmuData);
    // 监听弹幕容器的大小变化,更新弹幕位置
    new ResizeObserver(updateDanmuPositions).observe(danmuContainer);
})();

建议搭配 linux.do看帖懒人神器使用:

效果图:

23 个赞

因为自己没有搭建服务,当前弹幕来源是当前帖子。
未开循环播放。

3 个赞

66666

3 个赞

666,又多一个插件

4 个赞

整活还得是你啊

5 个赞

你就说,有没有氛围吧?

6 个赞

你们是真的会玩呐

6 个赞

@neo 出一个官方版吧

9 个赞

又来一个整活的。

6 个赞

始皇怕是不想写这部分代码

6 个赞

点赞收藏666

5 个赞

666~~这个idea 很赞啊!论坛的氛围、互动和趣味一下子就上去了,赞赞赞!

如果能变成类似视频弹幕那样,从右往左,就更棒啦

5 个赞

不是需要官方可见的数据,一般我是不打算出官方版的。
出官方版无异于跟开发者抢食,不利于生态。 :grin:

14 个赞

牛逼,还能这么玩

2 个赞

几点原因吧:
1、左侧右侧有很多空间,是空闲不占用的,右侧有个时间轴,始皇还有个目录控件,所以选择了占用左侧这个空间。
2、如果横着显示左侧空间太窄,如果全屏显示,会与文字重叠,影响阅读体验。
3、弹幕其实是个层,如果与页面重叠,会影响页面的点击和控制等操作。
4、【重点】始皇用户名是 @neo ,这个竖着的弹幕,也是为了致敬《黑客帝国》的数字雨。

6 个赞

有趣。

不过能否做成弹幕从屏幕边缘外进入而不是从边缘附近突然出现一大串。

2 个赞

真玩出花了,这个论坛

2 个赞

城会玩哈哈哈哈

2 个赞

6666

1 个赞

6的起飞了

1 个赞