马黑黑 发表于 2025-6-24 08:07

三亩地·寻

本帖最后由 马黑黑 于 2025-6-24 08:10 编辑 <br /><br /><style>
   #tz { 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/w4/xy.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
    #btnFs { bottom: 30px; color: #eee; }
    #player { position: absolute; left: -1000px; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); pointer-events: none; }
</style>

<div id="tz">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=31445474" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/05/18/16/40/video63663808aba6e.mp4" autoplay loop muted></video>
    <div id="player"></div>
</div>

<script type="module">
    import { THREE, scene, camera, renderer, clock, basic3, click3 } from 'https://638183.freep.cn/638183/3dev/3/3basic.js';
    import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

    FS(tz, player);
    basic3(tz);

    const group = new THREE.Group(), sGroup = new THREE.Group;
    const tt = 40, poses = [ , [-2, 0, 0], , , ];
    // 圆环
    for (let i = 0; i < tt; i ++) {
      const ellipse = drawEllipse(1.2, 0.8);
      ellipse.rotateY(THREE.MathUtils.degToRad(360 / tt * i));
      group.add(ellipse);
    }
    // 球
    poses.forEach( (pos, key) => {
      const texture = new THREE.TextureLoader().load('https://638183.freep.cn/638183/small/texture/wdrop.jpg');
      texture.colorSpace = THREE.SRGBColorSpace;
      const mesh = new THREE.Mesh(
            new THREE.SphereGeometry(0.25),
            new THREE.MeshBasicMaterial({ map: texture })
      );
      mesh.position.set(pos, pos, pos);
      if (key === 0) mesh.scale.set(2, 2, 2);
      sGroup.add(mesh);
    });
   
    sGroup.rotateX(-0.15);
    group.add(sGroup);

    scene.add(group);
    animate();

    aud.onplaying = aud.onpause = () => aud.paused ? clock.stop() : clock.start();

    tz.onclick = (e) => { if (click3(group, e)) player.click() };

    tz.onmousemove = (e) => {
      tz.title = click3(group, e) ? '播放/暂停' : '';
      tz.style.cursor = click3(group, e) ? 'pointer' : 'default';
    }

    // 绘制圆环函数
    function drawEllipse(r1, r2) {
      const curve = new THREE.EllipseCurve(0, 0, r1, r2, 0, 2 * Math.PI, false, 0);
      const arc = new THREE.Line(
            new THREE.BufferGeometry().setFromPoints( curve.getPoints(50) ),
            new THREE.LineDashedMaterial( { color: 0xffffff * Math.random(), dashSize: 0.02, gapSize: 0.02 } )
      );
      arc.computeLineDistances(); // 显示虚线必须计算线距
      return arc;
    }

    function animate() {
      requestAnimationFrame(animate);
      const delta = clock.getDelta();
      group.rotation.y += delta / 5;
      sGroup.children.forEach(child => child.rotation.y += delta);
      renderer.render(scene, camera);
    }
</script>

马黑黑 发表于 2025-6-24 08:10

帖子代码
<style>
   #tz { 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/w4/xy.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
    #btnFs { bottom: 30px; color: #eee; }
    #player { position: absolute; left: -1000px; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); pointer-events: none; }
</style>

<div id="tz">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=31445474" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/05/18/16/40/video63663808aba6e.mp4" autoplay loop muted></video>
    <div id="player"></div>
</div>

<script type="module">
    import { THREE, scene, camera, renderer, clock, basic3, click3 } from 'https://638183.freep.cn/638183/3dev/3/3basic.js';
    import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

    FS(tz, player);
    basic3(tz);

    const group = new THREE.Group(), sGroup = new THREE.Group;
    const tt = 40, poses = [ , [-2, 0, 0], , , ];
    // 圆环
    for (let i = 0; i < tt; i ++) {
      const ellipse = drawEllipse(1.2, 0.8);
      ellipse.rotateY(THREE.MathUtils.degToRad(360 / tt * i));
      group.add(ellipse);
    }
    // 球
    poses.forEach( (pos, key) => {
      const texture = new THREE.TextureLoader().load('https://638183.freep.cn/638183/small/texture/wdrop.jpg');
      texture.colorSpace = THREE.SRGBColorSpace;
      const mesh = new THREE.Mesh(
            new THREE.SphereGeometry(0.25),
            new THREE.MeshBasicMaterial({ map: texture })
      );
      mesh.position.set(pos, pos, pos);
      if (key === 0) mesh.scale.set(2, 2, 2);
      sGroup.add(mesh);
    });
   
    sGroup.rotateX(-0.15);
    group.add(sGroup);

    scene.add(group);
    animate();

    aud.onplaying = aud.onpause = () => aud.paused ? clock.stop() : clock.start();

    tz.onclick = (e) => { if (click3(group, e)) player.click() };

    tz.onmousemove = (e) => {
      tz.title = click3(group, e) ? '播放/暂停' : '';
      tz.style.cursor = click3(group, e) ? 'pointer' : 'default';
    }

    // 绘制圆环函数
    function drawEllipse(r1, r2) {
      const curve = new THREE.EllipseCurve(0, 0, r1, r2, 0, 2 * Math.PI, false, 0);
      const arc = new THREE.Line(
            new THREE.BufferGeometry().setFromPoints( curve.getPoints(50) ),
            new THREE.LineDashedMaterial( { color: 0xffffff * Math.random(), dashSize: 0.02, gapSize: 0.02 } )
      );
      arc.computeLineDistances(); // 显示虚线必须计算线距
      return arc;
    }

    function animate() {
      requestAnimationFrame(animate);
      const delta = clock.getDelta();
      group.rotation.y += delta / 5;
      sGroup.children.forEach(child => child.rotation.y += delta);
      renderer.render(scene, camera);
    }
</script>

马黑黑 发表于 2025-6-24 08:28

本帖最后由 马黑黑 于 2025-6-24 08:30 编辑

ThreeJS部分解释:

虚线圆环共 40 个,通过旋转组成球体。圆环使用 ElliesCurve 即椭圆曲线构建,参数1、2为椭圆圆心XY坐标,参数3为 rx 半径、参数4为 ry 半径,参数6值为 2 * Math.PI 时将是封闭的椭圆,而当 rx=ry,所创建的将是正圆(本帖画的是椭圆)。材质使用 LineDashMaterial 虚线材质,设置好虚线尺寸、虚线间距,最后还要计算线距。为方便复用,绘制圆环工作放在函数 drawEllipse(r1,r2),所需参数对应椭圆的 rx、ry,代码在 57~66 行,具体绘制和构图代码在 22~28 行。

圆环放入 group 组。

圆球5个,放入 sGroup 组。圆球绘制前事先设计一个3d位置数组,再根据数组绘制数组长度个圆球并按数组元素的数据各归其位,第一个圆球放大两倍。

sGroup 组存入 group 组,这样,71 行的动画指令对 sGroup 圆球组同样产生作用,因为它们是父子关系,group 为父,sGroup 为子,子对象随父对象运动——这和 HTML 关键帧动画理念是延承的。

红影 发表于 2025-6-24 08:34

前面的没记住,又要回去看看那个线性的椭圆和做法和球体的做法了{:4_173:}

红影 发表于 2025-6-24 08:36

这个还挺复杂,40条圆环的绘制在动画设置时还要重新考虑。

红影 发表于 2025-6-24 08:38

制作很漂亮,这样的背景加独特的视频,营造了很迷幻的效果。
那个球体上的贴纸有变形呢,变形却恰恰带来了奇妙的效果{:4_199:}

梦江南 发表于 2025-6-24 08:39

欣赏老师的精彩制作。祝夏安!

红影 发表于 2025-6-24 08:46

马黑黑 发表于 2025-6-24 08:28
ThreeJS部分解释:

虚线圆环共 40 个,通过旋转组成球体。圆环使用 ElliesCurve 即椭圆曲线构建,参数1 ...

原来圆环是父,圆球是子{:4_173:}

朵拉 发表于 2025-6-24 10:02

高科技,精彩{:4_178:}

杨帆 发表于 2025-6-24 11:46

感谢老师经典讲授,谢谢老师精彩示范,为马老师点赞{:4_191:}

马黑黑 发表于 2025-6-24 12:12

杨帆 发表于 2025-6-24 11:46
感谢老师经典讲授,谢谢老师精彩示范,为马老师点赞

{:4_191:}

马黑黑 发表于 2025-6-24 12:12

朵拉 发表于 2025-6-24 10:02
高科技,精彩

{:4_190:}

马黑黑 发表于 2025-6-24 12:13

红影 发表于 2025-6-24 08:46
原来圆环是父,圆球是子

ThreeJS网格(Mess)对象可以包含

马黑黑 发表于 2025-6-24 12:13

梦江南 发表于 2025-6-24 08:39
欣赏老师的精彩制作。祝夏安!

{:4_190:}

马黑黑 发表于 2025-6-24 12:14

红影 发表于 2025-6-24 08:38
制作很漂亮,这样的背景加独特的视频,营造了很迷幻的效果。
那个球体上的贴纸有变形呢,变形却恰恰带来了 ...

矩形上的平面图像,除非专门为圆球设计,否则贴上去后都会变形

马黑黑 发表于 2025-6-24 12:15

红影 发表于 2025-6-24 08:36
这个还挺复杂,40条圆环的绘制在动画设置时还要重新考虑。

动画设置不考虑什么,动画是针对 group 组不针对圆环个体

马黑黑 发表于 2025-6-24 12:15

红影 发表于 2025-6-24 08:34
前面的没记住,又要回去看看那个线性的椭圆和做法和球体的做法了

记不住查查资料,这是常规做法

红影 发表于 2025-6-24 15:13

马黑黑 发表于 2025-6-24 12:13
ThreeJS网格(Mess)对象可以包含

嗯嗯,把它们全包含进去了。

红影 发表于 2025-6-24 15:14

马黑黑 发表于 2025-6-24 12:14
矩形上的平面图像,除非专门为圆球设计,否则贴上去后都会变形

是的,除非那张地球图,是专门为球体设计的。
这里这个变形挺好的,很奇妙呢{:4_173:}

红影 发表于 2025-6-24 15:16

马黑黑 发表于 2025-6-24 12:15
动画设置不考虑什么,动画是针对 group 组不针对圆环个体

嗯嗯,前面看的时候还没看到讲解资料,是自己在盲猜中{:4_173:}
页: [1] 2 3
查看完整版本: 三亩地·寻