马黑黑 发表于 2025-7-19 17:41

魔幻立体球演示

<style>
#player {
        margin: 100px 0 100px calc(50% - 150px);
        position: relative;
        width: 300px;
        height: 300px;
        border-radius: 50%;
        background: radial-gradient(beige, skyblue);
        perspective: 600px;
        transform-style: preserve-3d;
}
.ring {
        position: absolute;
        width: 100%;
        height: 100%;
        border: thick dashed var(--cc);
        border-radius: 50%;
        transform: translateZ(-30px) rotateX(var(--ax)) rotateY(var(--ay));
}
</style>

<div id="player" title="播放/暂停"></div>

<script>
        var total = 15, rings = [], step = 0.5, isRun = false, raf;

        Array.from({length: total}).forEach( (d,k) => {
                d = document.createElement('div');
                d.className = 'ring';
                const a = k * 360 / total;
                d.style.cssText += `
                        --ax: ${a}deg;
                        --ay: ${a}deg;
                        --cc: #${Math.random().toString(16).substring(2,8)};
                `;
                rings.push({ elm: d, a: a });
                player.appendChild(d);
        });

        const animate = () => {
                rings.forEach( (d, k) => {
                        d.a = d.a + step;
                        d.elm.style.setProperty('--ax', d.a + 'deg');
                        d.elm.style.setProperty('--ay', d.a + 'deg');
                });
                raf = requestAnimationFrame(animate);
        };

        player.onclick = () => {
                isRun = !isRun;
                isRun ? animate() : cancelAnimationFrame(raf);
        };
</script>

马黑黑 发表于 2025-7-19 17:41

代码

<style>
    #player {
      margin: 100px 0 100px calc(50% - 150px);
      position: relative;
      width: 300px;
      height: 300px;
      border-radius: 50%;
      background: radial-gradient(beige, skyblue);
      perspective: 600px;
      transform-style: preserve-3d;
    }
    .ring {
      position: absolute;
      width: 100%;
      height: 100%;
      border: thick dashed var(--cc);
      border-radius: 50%;
      transform: translateZ(-30px) rotateX(var(--ax)) rotateY(var(--ay));
    }
</style>

<div id="player" title="播放/暂停"></div>

<script>
    var total = 15, rings = [], step = 0.5, isRun = false, raf;

    Array.from({length: total}).forEach( (d,k) => {
      d = document.createElement('div');
      d.className = 'ring';
      const a = k * 360 / total;
      d.style.cssText += `
            --ax: ${a}deg;
            --ay: ${a}deg;
            --cc: #${Math.random().toString(16).substring(2,8)};
      `;
      rings.push({ elm: d, a: a });
      player.appendChild(d);
    });

    const animate = () => {
      rings.forEach( (d, k) => {
            d.a = d.a + step;
            d.elm.style.setProperty('--ax', d.a + 'deg');
            d.elm.style.setProperty('--ay', d.a + 'deg');
      });
      raf = requestAnimationFrame(animate);
    };

    player.onclick = () => {
      isRun = !isRun;
      isRun ? animate() : cancelAnimationFrame(raf);
    };
</script>

马黑黑 发表于 2025-7-19 17:56

CSS和HTML:

容器元素 player 设置为 300*300 的尺寸,子元素 ring 圆环每一个都和父元素一样大小,然后在X轴、Y轴上均匀旋转,使用的CSS变量分别是 --ax、--ay,它们在后续JS中赋值,--ax 其实等于 --ay,之所以设置两个变量,最初考虑是让这两个值有所不同——这也许是另一种可能。

translateZ(-30px) 仅是在层次上做一点点距离拉开,不要的话默认圆环在Z轴上都是0.

JS相对简单:

变量 total 是圆环总数,rings 是圆环数组,step 是圆环旋转幅度,isRun 是动画运行开关,raf 是请求关键帧动画 requestanimationframe ID。

根据 total 变量创建圆环,圆环使用 div 标签,CSS类名为 ring,圆环的旋转角度平均化,并记录圆环的名称和所分配的角度到数组 rings 中。

动画函数 animate,遍历 rings 数组,改变其角度值,并将·改变的值设置到 --ax 和 --ay 这两个CSS变量,然后通过 requestanimationframe API 递归调用函数自身,形成持续运行动画的效果。

动画可控。作为演示,使用 player 的点击事件来完成:每一次单击它时,动画开关变量取反,即真时变为假、假时变为真,然后依据 isRun 的值决定时播放动画还是取消动画。

马黑黑 发表于 2025-7-19 17:58

圆环边框有多种选择,包括粗细、样式在内。圆环边框颜色可以不随机。

step 角度增幅可以根据需要设置为不同的数值。

红影 发表于 2025-7-19 20:44

这些圆环因为有立体的远近而线条的粗细不同,随着角度变化着,很奇妙{:4_199:}

杨帆 发表于 2025-7-19 21:05

奇妙的构思,魔幻的效果,谢谢马老师经典讲授与分享{:4_190:}

马黑黑 发表于 2025-7-19 23:53

杨帆 发表于 2025-7-19 21:05
奇妙的构思,魔幻的效果,谢谢马老师经典讲授与分享

{:4_191:}

马黑黑 发表于 2025-7-19 23:53

红影 发表于 2025-7-19 20:44
这些圆环因为有立体的远近而线条的粗细不同,随着角度变化着,很奇妙

CSS的真三维和模拟三维是不一样的

红影 发表于 2025-7-20 14:23

马黑黑 发表于 2025-7-19 23:53
CSS的真三维和模拟三维是不一样的

还有真三维?不是都是模拟的么?

马黑黑 发表于 2025-7-20 16:07

红影 发表于 2025-7-20 14:23
还有真三维?不是都是模拟的么?

你设置了 perspective 和 transform 3d,它就是真三维的模拟,假三维模拟指通过阴影等手段实现,不启用三维视图。

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

马黑黑 发表于 2025-7-20 16:07
你设置了 perspective 和 transform 3d,它就是真三维的模拟,假三维模拟指通过阴影等手段实现,不启用三 ...

哦,假三维是指阴影等手段的运用啊。嗯嗯,知道了{:4_187:}

马黑黑 发表于 2025-7-20 18:58

红影 发表于 2025-7-20 18:51
哦,假三维是指阴影等手段的运用啊。嗯嗯,知道了

{:4_190:}

红影 发表于 2025-7-20 22:06

马黑黑 发表于 2025-7-20 18:58


其实都不是真的,只是假三维的更假点{:4_173:}
页: [1]
查看完整版本: 魔幻立体球演示