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

Row

<style>
        #tz { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #eee url('https://638183.freep.cn/638183/t24/w4/row.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
        #btnFs { bottom: 20px; color: #eee; text-align: center; }
        #btnFs:hover { color: red; }
        #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=1328534807" autoplay loop></audio>
        <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/05/08/05/29/video6365a8c98c8e9.mp4" autoplay loop muted></video>
        <div id="player" title="播放/暂停"></div>
</div>

<script type="module">
        import * as THREE from 'https://638183.freep.cn/638183/3dev/build/three.module.min.js';
        import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(45, tz.offsetWidth/tz.offsetHeight, 0.1, 1000);
        camera.position.set(0, 0, 120);
        const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        renderer.setSize(tz.offsetWidth, tz.offsetHeight);
        const clock = new THREE.Clock();
        tz.appendChild(renderer.domElement);

        const boxGeometry = new THREE.BoxGeometry(30, 20, 5, 16, 8, 4);
        const ballGeometry = new THREE.SphereGeometry(10, 32, 32);
        const pointsMaterial = new THREE.PointsMaterial({ color: 0x00eeff, size: 1.2 });
        const box = new THREE.Points(boxGeometry, pointsMaterial);
        const ball = new THREE.Points(ballGeometry, pointsMaterial);
        box.rotateX(Math.PI / 4);
        box.position.set(-60, 20, 0);
        box.add(ball);
        scene.add(box);

        const isMess = (event) => {
                const raycaster = new THREE.Raycaster();
                const pointer = new THREE.Vector2();
                let intersects = [];
                pointer.x = (event.offsetX / tz.offsetWidth) * 2 - 1;
                pointer.y = -(event.offsetY / tz.offsetHeight) * 2 + 1;
                raycaster.setFromCamera(pointer, camera);
                intersects = raycaster.intersectObjects(, true);
                return intersects.length > 0;
        }

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

        tz.onclick = (e) => {
                if (isMess(e)) player.click();
        };

        const animate = () => {
                requestAnimationFrame(animate);
                const delta = clock.getDelta();
                box.rotation.y -= delta;
                renderer.render(scene, camera);
        };

        window.onresize = () => {
                camera.aspect = tz.offsetWidth / tz.offsetHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(tz.offsetWidth, tz.offsetHeight);
        };

        document.onvisibilitychange = () => {
                if (aud.paused) return;
                document.visibilityState === 'hidden' ? clock.stop() : clock.start();
        };

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

        animate();
        FS(tz, player);
</script>

马黑黑 发表于 2025-6-10 19:09

帖子代码

<style>
        #tz { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #eee url('https://638183.freep.cn/638183/t24/w4/row.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
        #btnFs { bottom: 20px; color: #eee; text-align: center; }
        #btnFs:hover { color: red; }
        #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=1328534807" autoplay loop></audio>
        <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/05/08/05/29/video6365a8c98c8e9.mp4" autoplay loop muted></video>
        <div id="player" title="播放/暂停"></div>
</div>

<script type="module">
        import * as THREE from 'https://638183.freep.cn/638183/3dev/build/three.module.min.js';
        import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(45, tz.offsetWidth/tz.offsetHeight, 0.1, 1000);
        camera.position.set(0, 0, 120);
        const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        renderer.setSize(tz.offsetWidth, tz.offsetHeight);
        const clock = new THREE.Clock();
        tz.appendChild(renderer.domElement);

        const boxGeometry = new THREE.BoxGeometry(30, 20, 5, 16, 8, 4);
        const ballGeometry = new THREE.SphereGeometry(10, 32, 32);
        const pointsMaterial = new THREE.PointsMaterial({ color: 0x00eeff, size: 1.2 });
        const box = new THREE.Points(boxGeometry, pointsMaterial);
        const ball = new THREE.Points(ballGeometry, pointsMaterial);
        box.rotateX(Math.PI / 4);
        box.position.set(-60, 20, 0);
        box.add(ball);
        scene.add(box);

        const isMess = (event) => {
                const raycaster = new THREE.Raycaster();
                const pointer = new THREE.Vector2();
                let intersects = [];
                pointer.x = (event.offsetX / tz.offsetWidth) * 2 - 1;
                pointer.y = -(event.offsetY / tz.offsetHeight) * 2 + 1;
                raycaster.setFromCamera(pointer, camera);
                intersects = raycaster.intersectObjects(, true);
                return intersects.length > 0;
        }

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

        tz.onclick = (e) => {
                if (isMess(e)) player.click();
        };

        const animate = () => {
                requestAnimationFrame(animate);
                const delta = clock.getDelta();
                box.rotation.y -= delta;
                renderer.render(scene, camera);
        };

        window.onresize = () => {
                camera.aspect = tz.offsetWidth / tz.offsetHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(tz.offsetWidth, tz.offsetHeight);
        };

        document.onvisibilitychange = () => {
                if (aud.paused) return;
                document.visibilityState === 'hidden' ? clock.stop() : clock.start();
        };

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

        animate();
        FS(tz, player);
</script>

马黑黑 发表于 2025-6-10 19:09

本帖最后由 马黑黑 于 2025-6-10 20:30 编辑

本帖主要是尝试点材质 THREE.PointsMaterial

该材质可以用于任何几何体(Geometry),它只渲染几何体的顶点。几何体的顶点,以立方体 BoxGeometry 为例,默认时是八个,但我们已经知道,几何体的面是可以有分段数的,一般分为宽高深三个方向的分段数,这种情形下,分段数的设置会形成几何体的面上的顶点,分段数越多顶点越密集,下面这行代码:

    const boxGeometry = new THREE.BoxGeometry(30, 20, 5, 16, 8, 4);

立方体几何体在xyz上的长度距离分别为 30、20、5 个距离单位,16、8、4 则分别是在xyz上的分段数,这样立方体上的顶点就不止8个了,每一个面上都有其它的顶点存在。

当使用点材质 THREE.PointsMaterial 与任意几何体,它们都是以“点”的方式渲染几何体的顶点,面上的不渲染。所以,要设计一下“点”的大小,缺省默认是 1 ,“点”缺省默认的颜色是白色 0xffffff。

注意观察相机的位置设置:

    camera.position.set(0, 0, 120);

在 Z轴 上距离单位为 120,比较大,所以几何体的长宽深设为 30、20、5,点材质 THREE.PointsMaterial 的 size 属性设为 1.2;若相机的 Z轴 上的距离单位改变,这些数据也应跟着改变。

帖子中,球体也是用相同的点材质 THREE.PointsMaterial ,球体只有横纵两个分段数(球体只有一个面),设为 32、32。

红影 发表于 2025-6-10 19:52

这个帖子应该是讲pointsMaterial的吧,看到通过设置,能让它勾勒出绘制的球体和立方体{:4_187:}

红影 发表于 2025-6-10 19:53

这场景设置很奇妙,视频使用也很相配呢{:4_187:}

马黑黑 发表于 2025-6-10 19:59

红影 发表于 2025-6-10 19:52
这个帖子应该是讲pointsMaterial的吧,看到通过设置,能让它勾勒出绘制的球体和立方体

这是要准备解释的材质。家里?

马黑黑 发表于 2025-6-10 19:59

红影 发表于 2025-6-10 19:53
这场景设置很奇妙,视频使用也很相配呢

那里的视频应有尽有

花飞飞 发表于 2025-6-10 20:15

pointsMaterial这个全是矩阵小点,球体和长方体全用了它做材质。。。
长方体设了几个点,就控制了大小和形状。。球体三个数据可以控制球体大小和点点排列疏密。。

花飞飞 发表于 2025-6-10 20:18

球体和长方体结合在一起的几何体做小播,直接点击小播控制播放暂停,
第五行#player的左位负一千没啥用的吧。。
反正小播不管到哪都可以控制动态

花飞飞 发表于 2025-6-10 20:21

背景暗黑,有点哥特风的美感,场景宏大。。
视频运动轨迹和小播完美衔接。。。。飞扬的粒子灵动好看。。
音乐节奏感强,好听

马黑黑 发表于 2025-6-10 20:30

花飞飞 发表于 2025-6-10 20:15
pointsMaterial这个全是矩阵小点,球体和长方体全用了它做材质。。。
长方体设了几个点,就控制了大小和形 ...

具体看三楼,刚刚写好

马黑黑 发表于 2025-6-10 20:31

花飞飞 发表于 2025-6-10 20:18
球体和长方体结合在一起的几何体做小播,直接点击小播控制播放暂停,
第五行#player的左位负一千没啥用的 ...

就是不让它出现,它的点击动作由ThreeJS绘制的图像接管

马黑黑 发表于 2025-6-10 20:32

花飞飞 发表于 2025-6-10 20:21
背景暗黑,有点哥特风的美感,场景宏大。。
视频运动轨迹和小播完美衔接。。。。飞扬的粒子灵动好看。。
...

{:4_191:}

花飞飞 发表于 2025-6-10 20:50

马黑黑 发表于 2025-6-10 19:09
本帖主要是尝试点材质 THREE.PointsMaterial

该材质可以用于任何几何体(Geometry),它只渲染几何体的 ...

没看到说明之前就是盲猜。。
原来点的大小是1.2,颜色也是自己根据贴子背景设定的。

几何体的长宽深和相机的位置有关联,数据设定还是很巧妙的,需要多试几次才能不变形

马黑黑 发表于 2025-6-10 21:46

花飞飞 发表于 2025-6-10 20:50
没看到说明之前就是盲猜。。
原来点的大小是1.2,颜色也是自己根据贴子背景设定的。



对,距离没有单位,文档也没有特别详细的说明,很多需要尝试

杨帆 发表于 2025-6-10 22:09

有益探索,奇特效果,视听盛宴,经典分享{:4_191:}

朵拉 发表于 2025-6-10 22:22

这个漂亮,有空学习一下{:4_204:}

马黑黑 发表于 2025-6-10 23:11

朵拉 发表于 2025-6-10 22:22
这个漂亮,有空学习一下

{:4_191:}

马黑黑 发表于 2025-6-10 23:11

杨帆 发表于 2025-6-10 22:09
有益探索,奇特效果,视听盛宴,经典分享

{:4_191:}

樵歌 发表于 2025-6-11 07:35

地狱还是天堂,{:4_203:}
页: [1] 2 3 4 5 6 7
查看完整版本: Row