Solar Echoes
<style>#tz { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); min-height: 80vh; aspect-ratio: 16/9; background: #eee url('https://638183.freep.cn/638183/t24/webp3/echo.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
#player { position: absolute; width: 15vw; height: auto; aspect-ratio: 1/1; cursor: pointer; background: none; border-radius: 50%; transform: translateX(-20px); }
#btnFs { bottom: 20px; color: #eee; text-align: center; }
#btnFs:hover { color: red; }
#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=29753363" autoplay loop></audio>
<video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/03/19/50/54/video6363ab1e86aba.mp4" autoplay loop muted></video>
<div id="player" title="播放/暂停"></div>
</div>
<script type="module">
import * as THREE from 'https://unpkg.ihwx.cn/three@0.176.0/build/three.module.js';
import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';
const scene = new THREE.Scene();
const clock = new THREE.Clock();
const camera = new THREE.PerspectiveCamera(60, tz.offsetWidth / tz.offsetHeight, 1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(tz.offsetWidth, tz.offsetHeight);
tz.appendChild(renderer.domElement);
const circle = new THREE.Mesh(
new THREE.CircleGeometry(1,3),
new THREE.MeshNormalMaterial({ side: THREE.DoubleSide })
);
const mesh = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 0.5, 128, 1),
new THREE.MeshNormalMaterial({ wireframe: true })
);
mesh.add(circle);
mesh.position.set(-0.15, 0, 0);
scene.add(mesh);
let data = 150, lastUpdateTime = 0;
const interval = setInterval(() => data = aud.paused ? 150 : 200 - Math.floor(Math.random() * 100) ,150);
const animate = (currentTime) => {
const delta = clock.getDelta();
mesh.rotation.x = data / 150;
mesh.rotation.y -= delta / 5;
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
aud.onplaying = aud.onpause = () => aud.paused ? clock.stop() : clock.start();
animate();
FS(tz, player);
</script> 帖子代码
<style>
#tz { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); min-height: 80vh; aspect-ratio: 16/9; background: #eee url('https://638183.freep.cn/638183/t24/webp3/echo.webp') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
#player { position: absolute; width: 15vw; height: auto; aspect-ratio: 1/1; cursor: pointer; background: none; border-radius: 50%; transform: translateX(-20px); }
#btnFs { bottom: 20px; color: #eee; text-align: center; }
#btnFs:hover { color: red; }
#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=29753363" autoplay loop></audio>
<video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/22/11/03/19/50/54/video6363ab1e86aba.mp4" autoplay loop muted></video>
<div id="player" title="播放/暂停"></div>
</div>
<script type="module">
import * as THREE from 'https://unpkg.ihwx.cn/three@0.176.0/build/three.module.js';
import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';
const scene = new THREE.Scene();
const clock = new THREE.Clock();
const camera = new THREE.PerspectiveCamera(60, tz.offsetWidth / tz.offsetHeight, 1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(tz.offsetWidth, tz.offsetHeight);
tz.appendChild(renderer.domElement);
const circle = new THREE.Mesh(
new THREE.CircleGeometry(1,3),
new THREE.MeshNormalMaterial({ side: THREE.DoubleSide })
);
const mesh = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 0.5, 128, 1),
new THREE.MeshNormalMaterial({ wireframe: true })
);
mesh.add(circle);
mesh.position.set(-0.15, 0, 0);
scene.add(mesh);
let data = 150, lastUpdateTime = 0;
const interval = setInterval(() => data = aud.paused ? 150 : 200 - Math.floor(Math.random() * 100) ,150);
const animate = (currentTime) => {
const delta = clock.getDelta();
mesh.rotation.x = data / 150;
mesh.rotation.y -= delta / 5;
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
aud.onplaying = aud.onpause = () => aud.paused ? clock.stop() : clock.start();
animate();
FS(tz, player);
</script>
本帖:
原本是做基于 ThreeJS 音频动态响应的,因为音频数据解析的跨域问题,将 Audio 部分的内容去掉,使用 setInterval 定时器提供一个X轴变更数据。
ThreeJS 集成有一个音频加载器,能播放音频并获取音频相关数据。下面的链接是一个简单的演示,不过由于空间在境外,音频的读取速度会慢一些(能科学上网的音频加载的速度会较快):
怪我无情
附:ThreeJS Audio 演示代码(需要web页与音频资源同源或音频资源支持跨域解析)
<div id="tz" style="margin: 20px auto; width: 100%; height: 640px; position: relative;"></div>
<script type="module">
import * as THREE from 'https://unpkg.ihwx.cn/three@0.176.0/build/three.module.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, tz.offsetWidth / tz.offsetHeight, 1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(tz.offsetWidth, tz.offsetHeight);
tz.appendChild(renderer.domElement);
const listener = new THREE.AudioListener(); // 音频监听器
camera.add(listener); // 安在相机上
const sound = new THREE.Audio(listener); // 音频源
const audioLoader = new THREE.AudioLoader(); // 音频加载器
audioLoader.load('/upload/2025/怪我无情.mp3', (buffer) => {
sound.setBuffer(buffer);
sound.setLoop(true);
sound.play();
});
const analyser = new THREE.AudioAnalyser(sound, 32); // 音频数据分析器
// 绘制圆柱体图形
const mesh = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 0.25, 128, 1, false, 0, Math.PI * 1.75),
new THREE.MeshNormalMaterial({ wireframe: true })
);
scene.add(mesh);
// 动画 :圆柱体在X轴上与音频数据联动旋转、Y轴上自旋转
const animate = () => {
const data = analyser.getAverageFrequency() || 150;
mesh.rotation.x = data / 150;
mesh.rotation.y -= 0.01;//data / 200;
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
</script>
第 17 行的音频地址,换上自己的。如果是本地机测试效果,需要运行本地机虚拟服务器 好奇妙的效果,全屏时更觉得震撼。{:4_199:} 马黑黑 发表于 2025-6-2 18:07
本帖:
原本是做基于 ThreeJS 音频动态响应的,因为音频数据解析的跨域问题,将 Audio 部分的内容去掉, ...
这个《怪我无情》更好,完全和音乐节奏一致呢{:4_187:} 红影 发表于 2025-6-2 20:06
这个《怪我无情》更好,完全和音乐节奏一致呢
那个,圆柱体在X轴上的旋转绑定的是音乐提供的实时数据资源 红影 发表于 2025-6-2 19:57
好奇妙的效果,全屏时更觉得震撼。
背景挺好看的 震撼效应,饕餮大餐,谢谢马老师经典分享{:4_191:} 杨帆 发表于 2025-6-2 21:13
震撼效应,饕餮大餐,谢谢马老师经典分享
晚上好 马黑黑 发表于 2025-6-2 21:15
晚上好
老师好,基于 ThreeJS 的音频动态响应挺好玩,只是音频数据解析的跨域问题让人扫兴{:4_190:} 马黑黑 发表于 2025-6-2 20:26
那个,圆柱体在X轴上的旋转绑定的是音乐提供的实时数据资源
响应式的,特别好看。 马黑黑 发表于 2025-6-2 20:26
背景挺好看的
是啊,非常奇妙的效果{:4_199:} 红影 发表于 2025-6-2 22:35
是啊,非常奇妙的效果
乐曲也很好 红影 发表于 2025-6-2 22:34
响应式的,特别好看。
那是自然。我问DS能不能模仿,它说不行的 杨帆 发表于 2025-6-2 21:26
老师好,基于 ThreeJS 的音频动态响应挺好玩,只是音频数据解析的跨域问题让人扫兴
之前有过一个论坛开放的,后来又关闭了,还将俺的帐号删除了 马黑黑 发表于 2025-6-2 22:45
乐曲也很好
带点玄幻的味道{:4_187:} 马黑黑 发表于 2025-6-2 22:45
那是自然。我问DS能不能模仿,它说不行的
无法模仿,不能超越{:4_187:} 马黑黑 发表于 2025-6-2 22:46
之前有过一个论坛开放的,后来又关闭了,还将俺的帐号删除了
是啊,一个缺乏远见的论坛,自然也走不远