马黑黑 发表于 2025-7-18 14:30

外面的宇宙

<style>
        #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: url('https://638183.freep.cn/638183/t24/6/outspace.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; z-index: 1; overflow: hidden; display: grid; place-items: center; position: relative; }
        #player { position: absolute; bottom: 120px; aspect-ratio: 1/1; width: 15%; display: grid; place-items: center; animation: rot 12s linear infinite var(--state); transition: 0.6s; cursor: pointer; }
        li-zi { position: absolute; aspect-ratio: 1/1; width: 15%; border-radius: 50%; background: radial-gradient(circle at 10%, var(--c1), var(--c2)); box-shadow: inset 4px 4px 16px gray; transform: rotate(var(--a)) translate(var(--r)); transition: 0.7s; }
        #btnFs { bottom: 20px; color: #eee; }
        .vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .8; pointer-events: none; }
        @keyframes rot { to { transform: rotate(1turn); } }
</style>

<div id="papa">
        <audio id="aud" src="https://music.163.com/song/media/outer/url?id=2164895832" autoplay loop></audio>
        <video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/04/04/03/07/video63641e7be0306.mp4" autoplay loop muted></video>
        <div id="player"></div>
</div>

<script type="module">
        import { FS } from 'https://638183.freep.cn/638183/web/js/fullscreen.js';
        FS(papa, player);

        var posdata = , lzAr = [];

        posdata.forEach( (pos, posIdx) => {
                Array.from({ length: pos }).forEach( (lz, lzIdx) => {
                        lz = document.createElement('li-zi');
                        const a = lzIdx * 360 / pos, r = posIdx * player.clientWidth / (posdata.length + 1);
                        lz.style.cssText += `
                                --c1: #${Math.random().toString(16).substring(2, 8)};
                                --c2: #${Math.random().toString(16).substring(2, 8)};
                                --r: ${r}px;
                                --a: ${a}deg;
                        `;
                        lzAr.push({elm: lz, r: r, idx: posIdx});
                        player.appendChild(lz);
                });
        });

        aud.ontimeupdate = () => flash();

        window.onresize = () => {
                lzAr.forEach(lz => lz.elm.style.setProperty('--r', `${lz.idx * player.clientWidth / (posdata.length + 1)}px`));
        };

        function flash() {
                player.style.setProperty('filter', `hue-rotate(${360 * Math.random()}deg)`);
        }
</script>

马黑黑 发表于 2025-7-18 14:31

代码:

<style>
    #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: url('https://638183.freep.cn/638183/t24/6/outspace.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; z-index: 1; overflow: hidden; display: grid; place-items: center; position: relative; }
    #player { position: absolute; bottom: 120px; aspect-ratio: 1/1; width: 15%; display: grid; place-items: center; animation: rot 12s linear infinite var(--state); transition: 0.6s; cursor: pointer; }
    li-zi { position: absolute; aspect-ratio: 1/1; width: 15%; border-radius: 50%; background: radial-gradient(circle at 10%, var(--c1), var(--c2)); box-shadow: inset 4px 4px 16px gray; transform: rotate(var(--a)) translate(var(--r)); transition: 0.7s; }
    #btnFs { bottom: 20px; color: #eee; }
    .vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .8; pointer-events: none; }
    @keyframes rot { to { transform: rotate(1turn); } }
</style>

<div id="papa">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=2164895832" autoplay loop></audio>
    <video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/04/04/03/07/video63641e7be0306.mp4" autoplay loop muted></video>
    <div id="player"></div>
</div>

<script type="module">
    import { FS } from 'https://638183.freep.cn/638183/web/js/fullscreen.js';
    FS(papa, player);

    var posdata = , lzAr = [];

    posdata.forEach( (pos, posIdx) => {
      Array.from({ length: pos }).forEach( (lz, lzIdx) => {
            lz = document.createElement('li-zi');
            const a = lzIdx * 360 / pos, r = posIdx * player.clientWidth / (posdata.length + 1);
            lz.style.cssText += `
                --c1: #${Math.random().toString(16).substring(2, 8)};
                --c2: #${Math.random().toString(16).substring(2, 8)};
                --r: ${r}px;
                --a: ${a}deg;
            `;
            lzAr.push({elm: lz, r: r, idx: posIdx});
            player.appendChild(lz);
      });
    });

    aud.ontimeupdate = () => flash();

    window.onresize = () => {
      lzAr.forEach(lz => lz.elm.style.setProperty('--r', `${lz.idx * player.clientWidth / (posdata.length + 1)}px`));
    };

    function flash() {
      player.style.setProperty('filter', `hue-rotate(${360 * Math.random()}deg)`);
    }
</script>

马黑黑 发表于 2025-7-18 14:48

播放器适用容器元素尺寸机制:

播放器 #player 选择器宽度设置为 15%,这将令其尺寸是动态变化的——依据访问者的显示设备宽度而定,因为帖子容器的尺寸采用了自适应显示设备尺寸。

然后,借助CSS的 aspect-ratio 属性,强制小播宽高比一致(都是一比一)。

酱紫,其内的子元素 li-zi ,15%的宽度 + 一比一的 aspect-ratio 配套设置,小球也是自适应尺寸的。

一系列的自适应宽高,在不同分辨率下,呈现的小播及小播内的粒子(小球)大小不尽一致,但与帖子的宽高应该总是般配的,而同一显示设备下,浏览器窗口的尺寸变化小播会有过渡性的实时响应。

浏览器窗口的变更,需要重新计算各层粒子的 --r 变量,它规范粒子层之间的间隔(gap,其实就是最大范围半径),这个变量不好用相对单位表达,其计算依据是粒子容器即 player 的动态宽度和粒子所在的圈层(第39~41行代码)。

粒子分层呈现,最里层一个,然后第二、三、四层分别为5、10、15个,用数组 posdata 记录,代码在20行,可以给不同的层定义不同的粒子数,以及建立更多的层,但数量应恰当。

马黑黑 发表于 2025-7-18 14:50

小球的闪烁通过 flash 函数实现,借用的是 CSS 的滤镜属性,通过audio标签的 ontimeupdate 事件驱动。

马黑黑 发表于 2025-7-18 16:01

<p>音频:秋刀电音·外面的宇宙</p>
<script>
        aud.src = 'https://music.163.com/song/media/outer/url?id=2726392829';
</script>

清茶煮雪 发表于 2025-7-18 16:28

欣赏老师的精彩{:4_180:}

红影 发表于 2025-7-18 19:58

马黑黑 发表于 2025-7-18 14:50
小球的闪烁通过 flash 函数实现,借用的是 CSS 的滤镜属性,通过audio标签的 ontimeupdate 事件驱动。

一进来先注意的是小球的闪烁,那么玄妙,和背景十分协调{:4_199:}

红影 发表于 2025-7-18 20:02

马黑黑 发表于 2025-7-18 14:48
播放器适用容器元素尺寸机制:

播放器 #player 选择器宽度设置为 15%,这将令其尺寸是动态变化的——依 ...

原来这里面还有这么多的自适应设置,可以保证不同分辨率下,小球的分布于帖子的框相匹配,特地去试了一下,改变分辨率,小球果然有过渡性相应呢{:4_199:}

杨帆 发表于 2025-7-18 22:24

漂亮!谢谢马老师经典讲授和精彩示范{:4_190:}

马黑黑 发表于 2025-7-19 12:44

杨帆 发表于 2025-7-18 22:24
漂亮!谢谢马老师经典讲授和精彩示范

{:4_190:}

朵拉 发表于 2025-7-19 21:16

空灵,精彩{:4_178:}

朵拉 发表于 2025-7-19 21:21

老师好,学生已交作业,请您指正{:4_190:}
页: [1]
查看完整版本: 外面的宇宙