马黑黑 发表于 2025-7-10 07:51

Tupac Amaru

<style>
    #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #333 url('https://638183.freep.cn/638183/t24/6/tupac.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; perspective: 500px; z-index: 1; position: relative; --state: running; --z: -300px; }
    #btnFs { left: 15px; bottom: 20px; color: white; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .6; pointer-events: none; }
    #lzwrap { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; display: grid; place-items: center; }
    li-zi { position: absolute; width: 40px; height: 40px; border-radius: 50%; background: url('https://638183.freep.cn/638183/small/2025/b2.webp') no-repeat center/cover; cursor: pointer; transform: rotateY(0) translate3d(0, 40px, var(--z)) rotateY(0); animation: runcircle 30s var(--delay) linear infinite var(--state); }
    #player { position: absolute; width: 200px; height: 200px; background: url('https://638183.freep.cn/638183/small/2025/f1.webp') no-repeat center/cover; transform: rotateX(35deg) rotateZ(0); cursor: pointer; animation: rot3d 6s linear infinite var(--state); filter: drop-shadow(0 0 20px #333) opacity(0.8); }
    @keyframes rot3d { to { transform: rotateX(35deg) rotateZ(360deg); backface-visibility: visible; } }
    @keyframes runcircle { to { transform: rotateY(-360deg) translate3d(0, 40px, var(--z)) rotateY(360deg) rotateZ(-10turn); } }
</style>

<div id="papa">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=3934940" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/07/17/17/27/27/video66978e7fb1c4d.mp4" autoplay loop muted></video>
    <div id="lzwrap">
      <div id="player"></div>
    </div>
</div>

<script type="module">
    import { FS } from 'https://638183.freep.cn/638183/web/js/FS.js';

    var total = 20;

    Array.from({length: total}).forEach((lz, idx) => {
      lz = document.createElement('li-zi');
      lz.title = 'Alt+X';
      lz.style.cssText += `
            filter: hue-rotate(${360 * Math.random()}deg);
            --delay: -${idx * 30 / total}s;
      `;
      lz.onclick = () => player.click();
      lzwrap.appendChild(lz);
    });

    window.onresize = () => papa.style.setProperty('--z', -300 * papa.clientWidth/1400 + 'px');

    FS(papa, player);
</script>

马黑黑 发表于 2025-7-10 07:51

代码

<style>
    #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #333 url('https://638183.freep.cn/638183/t24/6/tupac.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; perspective: 500px; z-index: 1; position: relative; --state: running; --z: -300px; }
    #btnFs { left: 15px; bottom: 20px; color: white; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .6; pointer-events: none; }
    #lzwrap { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; display: grid; place-items: center; }
    li-zi { position: absolute; width: 40px; height: 40px; border-radius: 50%; background: url('https://638183.freep.cn/638183/small/2025/b2.webp') no-repeat center/cover; cursor: pointer; transform: rotateY(0) translate3d(0, 40px, var(--z)) rotateY(0); animation: runcircle 30s var(--delay) linear infinite var(--state); }
    #player { position: absolute; width: 200px; height: 200px; background: url('https://638183.freep.cn/638183/small/2025/f1.webp') no-repeat center/cover; transform: rotateX(35deg) rotateZ(0); cursor: pointer; animation: rot3d 6s linear infinite var(--state); filter: drop-shadow(0 0 20px #333) opacity(0.8); }
    @keyframes rot3d { to { transform: rotateX(35deg) rotateZ(360deg); backface-visibility: visible; } }
    @keyframes runcircle { to { transform: rotateY(-360deg) translate3d(0, 40px, var(--z)) rotateY(360deg) rotateZ(-10turn); } }
</style>

<div id="papa">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=3934940" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/07/17/17/27/27/video66978e7fb1c4d.mp4" autoplay loop muted></video>
    <div id="lzwrap">
      <div id="player"></div>
    </div>
</div>

<script type="module">
    import { FS } from 'https://638183.freep.cn/638183/web/js/FS.js';

    var total = 20;

    Array.from({length: total}).forEach((lz, idx) => {
      lz = document.createElement('li-zi');
      lz.title = 'Alt+X';
      lz.style.cssText += `
            filter: hue-rotate(${360 * Math.random()}deg);
            --delay: -${idx * 30 / total}s;
      `;
      lz.onclick = () => player.click();
      lzwrap.appendChild(lz);
    });

    window.onresize = () => papa.style.setProperty('--z', -300 * papa.clientWidth/1400 + 'px');

    FS(papa, player);
</script>

马黑黑 发表于 2025-7-10 07:54

3d关键帧动画设计及其原理可参阅:

    菇凉、竹子和CSS三维动画 - 马黑黑教程专版 - 花潮论坛 - Powered by Discuz!

马黑黑 发表于 2025-7-10 08:03

与菇凉竹子的设计相比,这里,关键帧动画多了一个 rotateZ() 旋转,因此小球在绕圈的同时还会自转。

小球原本就有Y轴上的自转,但又逆自转抵消回来。小球在Y轴Z轴上:

      Y轴自转+Z位移 => 驱动绕Y轴做绕圈运动
      Y轴逆向自转 => 抵消Y转上的自转
      Z轴上的自转 => 实际自转

本帖,Y轴上的逆向自转还有一个作用:保持小球原本面貌,不然它们会在某些转动角度下变成一个个纸片球

梦江南 发表于 2025-7-10 09:38

问好黑黑老师,谢谢精彩分享。祝夏安!{:4_190:}

红影 发表于 2025-7-10 10:59

马黑黑 发表于 2025-7-10 08:03
与菇凉竹子的设计相比,这里,关键帧动画多了一个 rotateZ() 旋转,因此小球在绕圈的同时还会自转。

小 ...

是的,这里多个Z轴旋转。
“Y轴上的逆向自转还有一个作用:保持小球原本面貌,”不会变成纸片球。

z轴上的转动却没这样的问题呢,这真奇怪,主要看着小球是平面转动,感觉是绕y的转动却是用绕z实现的。

红影 发表于 2025-7-10 11:05

rotateZ(-10turn); 这个怎么设这么大,通常有个2-3倍就够用了啊。

哦,是为了控制转速吧,runcircle 30s ,,这个没法设得时间太短,是为了配合player的转动的,那就只能选择10倍来控制小球的转速了吧{:4_173:}

红影 发表于 2025-7-10 11:11

window.onresize = (),,,,这个没看明白,是起什么作用的?

马黑黑 发表于 2025-7-10 12:13

红影 发表于 2025-7-10 11:11
window.onresize = (),,,,这个没看明白,是起什么作用的?

德文还看得懂不?英文德文差不多的。

window,视窗,指浏览器窗口可视部分——就是展示网页内容的那部分;
resize,尺寸重置,On是JS前缀,onresize 表示尺寸发生重置之时;

酱紫,window.onresize 的意思是视窗改变大小时。这个时候会触发函数体 { ... } 里面的指令执行:改变小球在 Z轴 上运行的距离变量 --z,以此来尽可能保证不同尺寸的视窗下小球的运行范围不突破容器边界或保持在一定范围之内。

当然,仅改变这个变量还不够,还需要设置容器的 perspective 属性值。这在我的网站里发布的帖子已经加入,有兴趣可以去瞧瞧那里的源码。

马黑黑 发表于 2025-7-10 12:16

红影 发表于 2025-7-10 11:05
rotateZ(-10turn); 这个怎么设这么大,通常有个2-3倍就够用了啊。

哦,是为了控制转速吧,runcircle 30s ...

30秒钟里在Z轴上自转的圈数,不多的。

一个运动周期时长为 30 秒,一个小球绕完一圈之时它就自转那么多圈。一切得看 duration-time 的设定

马黑黑 发表于 2025-7-10 12:21

红影 发表于 2025-7-10 10:59
是的,这里多个Z轴旋转。
“Y轴上的逆向自转还有一个作用:保持小球原本面貌,”不会变成纸片球。



XY两轴构成一个平面面对观者的眼睛;Z轴与该平面垂直。酱紫,小球在Z轴上的自转是不会改变角度的,因为它的方向和人眼看屏幕的方向一致,并永远保持着相一致的方向。你可以想象成Z轴上的转动就是一个平面上物体正逆时针的转动。

而在Y轴上自转,当它转到90度角时,物体的面(注意小球不是真正的3d物体,它是一个平面物体)分别朝左朝右,观者看到的只是一条直线甚至连直线都没有。在X轴上同理。

马黑黑 发表于 2025-7-10 12:21

梦江南 发表于 2025-7-10 09:38
问好黑黑老师,谢谢精彩分享。祝夏安!

{:4_190:}

马黑黑 发表于 2025-7-10 12:37

红影 发表于 2025-7-10 10:59
是的,这里多个Z轴旋转。
“Y轴上的逆向自转还有一个作用:保持小球原本面貌,”不会变成纸片球。


你后面提出的问题,谁和谁配合能产生物体做圆弧位置移动的运动即绕圈圈。这个解释过。

你可以先回到2dt ransform转换,很久以前专门介绍过:

    trnsform: rotate(deg) translateX/Y(px);

元素先自转再位移一定距离(xy方向任意一个都行),元素在自转的时候会绕圈走。参考一下以下代码,能理解了,理解3d的就有基础:

<style>
      #pa {
                margin: 20px;
                width: 100%;
                height: 600px;
                /* 下面两句将子元素绝对居中 */
                display: grid;
                place-items: center;
                position: relative;
      }
      #son {
                position: absolute;
                width: 100px;
                height: 100px;
                background: teal;
                animation: rot 6s linear infinite;
      }
      @keyframes rot {
                from { transform: rotate(0) translate(240px); }
                to { transform: rotate(360deg) translate(240px); }
      }
</style>

<div id="pa">
      <div id="son"></div>
</div>这个知识点其实很多人都过不了。几何能力问题吧。回头可以再看看我在菇凉竹子里的分析,里面说得明明白白了。

杨帆 发表于 2025-7-10 13:13

构思新颖,效果奇妙!谢谢马老师经典讲授与示范{:4_190:}

红影 发表于 2025-7-10 20:55

马黑黑 发表于 2025-7-10 12:13
德文还看得懂不?英文德文差不多的。

window,视窗,指浏览器窗口可视部分——就是展示网页内容的那部 ...

黑黑说得还真对,德文英文的确很相似。知道了,这个设置是保证小球在想要的范围里。{:4_187:}

红影 发表于 2025-7-10 20:57

马黑黑 发表于 2025-7-10 12:16
30秒钟里在Z轴上自转的圈数,不多的。

一个运动周期时长为 30 秒,一个小球绕完一圈之时它就自转那么 ...

嗯嗯,这个看需要而定,设完了看看效果也能调到自己喜欢的速度的{:4_187:}

红影 发表于 2025-7-10 20:59

马黑黑 发表于 2025-7-10 12:21
XY两轴构成一个平面面对观者的眼睛;Z轴与该平面垂直。酱紫,小球在Z轴上的自转是不会改变角度的,因为它 ...

我知道了,其实之前的播放器转动也都是绕z轴的呢,只是那时没设置三维,不用特地说明。

红影 发表于 2025-7-10 21:04

马黑黑 发表于 2025-7-10 12:37
你后面提出的问题,谁和谁配合能产生物体做圆弧位置移动的运动即绕圈圈。这个解释过。

你可以先回到2d ...

嗯嗯,如果没有位移,则原地自转,有位移则会绕圈了{:4_187:}

马黑黑 发表于 2025-7-10 22:36

红影 发表于 2025-7-10 20:55
黑黑说得还真对,德文英文的确很相似。知道了,这个设置是保证小球在想要的范围里。

这些语言有共同的祖先,词根很多是一样的

马黑黑 发表于 2025-7-10 22:41

红影 发表于 2025-7-10 21:04
嗯嗯,如果没有位移,则原地自转,有位移则会绕圈了

这个道理我在竹子那里有一点描述,应该很清晰的,大概是:元素的自转以自己的中心点为默认原点,它转动的同时位移,就会保持与原来中心点位移的距离,而且一直保持。

这好比绳子系着一个小球,然后固定绳子的另一端,让小球绕圈圈。绳子的作用就是不让小球脱离绳子的长度距离,酱紫就会促使小球做圆弧运动。translateX/Y/Z的距离就是绳子的长度。
页: [1] 2 3
查看完整版本: Tupac Amaru