three实现三维音频声音可视化频谱动画效果代码
代码语言:html
所属分类:多媒体
代码描述:three实现三维音频声音可视化频谱动画效果代码
代码标签: three 三维 音频 声音 可视化 频谱 动画
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import url('https://fonts.googleapis.com/css?family=Architects+Daughter|Orbitron'); * { margin: 0; padding: 0; } html, body { overflow: hidden; font-family:'Orbitron',sans-serif; font-size:14px; } /* dat.gui align to left */ .lil-gui.autoPlace{ right:auto !important; left:15px !important; } .Experience { position:relative; width:100vw; height:100vh; } .Experience > .Experience_Canvas { top:0; left:0; position:absolute; outline: none; filter:grayscale(0%); transition:filter 1s; } .Experience[loading = "true"] > .Experience_Canvas { filter:grayscale(90%); } .Experience_Panel { position:relative; border:1px solid #000022; background-color: rgba(30, 30, 90, 0.75); color:#FFFFFF; border-radius: 6px; box-shadow: 5px 5px 5px rgba(0,0,0, 0.5); } .Experience > .Experience_Loading { padding:0.6em; /* width:4em;*/ margin:auto; top: calc(50vh - 10px); height: 18px; display:none; font-family:'Orbitron',sans-serif; font-size:max(1.5vw, 1.5vh); } .Experience[loading = "true"] > .Experience_Loading { display:table; } /* Group of controls (fps, button logo, button full screen) */ .Experience_Controls { position:fixed; bottom :0; right:0; z-index:10000; } .Experience_Static, .Experience_Control { user-select: none; position:relative; width:48px; /*max(3.2vw, 3.2vh);*/ height:48px; /*max(3.2vw, 3.2vh);*/ margin-bottom:max(0.5vw, 0.5vh); margin-right:max(0.5vw, 0.5vh); padding:6px; /* padding:max(0.4vw, 0.4vh);*/ text-align: center; border:2px solid transparent; display: block; margin-left: auto; transition:border 0.4s; } .Experience_FPS { font-size:24px; } .Experience_TxtFPS { font-size:14px; } .Experience_Control:hover { border:2px solid rgb(234, 80, 78); cursor:pointer; } .Experience_Control > img { transition:transform 0.4s; width:48px; height:48px; position:relative; } .Experience_Control:hover > img { transform: scale(1.5, 1.5); } #restoreScreen { display:none; } #Logo { display: block; transition: width 0.33s ease-in; } /* Logo svg need to be fixed on the right, because of the letter logo animation */ #Logo img { position:absolute; right: 6px; } #Logo > * { pointer-events: none; } #Logo:hover { width:280px; } #Logo > #LogoText { position:absolute; bottom:14px; margin-top:3px; transition:0.4s; width:230px; /* 12 caracters * 400px */ font-size:24px; } #Logo > #LogoText > span { transition:0.33s cubic-bezier(.17,-0.42,0,1.15); opacity:0; position: relative; display: inline-block; color:#FFF; } #Logo:hover > #LogoText > span { position:relative; opacity:1; left:230px; animation: LogoAnimation 0.33s 0.33s cubic-bezier(.17,-0.42,0,1.15); animation-fill-mode:forwards; } /* Color rojo del 33 */ #Logo > #LogoText > span:nth-child(11), #Logo > #LogoText > span:nth-child(12) { color: rgb(234, 80, 78); } #Logo:hover > #LogoText > span:nth-child(1) { animation-delay: 0.55s; } #Logo:hover > #LogoText > span:nth-child(2) { animation-delay: 0.50s; } #Logo:hover > #LogoText > span:nth-child(3) { animation-delay: 0.45s; } #Logo:hover > #LogoText > span:nth-child(4) { animation-delay: 0.40s; } #Logo:hover > #LogoText > span:nth-child(5) { animation-delay: 0.35s; } #Logo:hover > #LogoText > span:nth-child(6) { animation-delay: 0.30s; } #Logo:hover > #LogoText > span:nth-child(7) { animation-delay: 0.25s; } #Logo:hover > #LogoText > span:nth-child(8) { animation-delay: 0.20s; } #Logo:hover > #LogoText > span:nth-child(9) { animation-delay: 0.15s; } #Logo:hover > #LogoText > span:nth-child(10) { animation-delay: 0.10s; } #Logo:hover > #LogoText > span:nth-child(11) { animation-delay: 0.05s; } #Logo:hover > #LogoText > span:nth-child(12) { animation-delay: 0.0s; } @keyframes LogoAnimation { 0% { left:230px; } 100% { left:0px; } } /* * Audio controls */ .Experience_AudioControls { user-select: none; position:fixed; display:flex; flex-flow: row; flex-direction:column; /* flex-wrap: wrap;*/ bottom:1vh; /* height:80px;*/ width:75vw; left:12.5vw; /* padding:0 0 min(1vw, 1vh) 0 0;*/ pointer-events: none; } .Experience_AudioControls label, .Experience_AudioControls button { font-size:14px !important; font-family:'Orbitron',sans-serif; } .Experience_AC_Play { /* margin:max(0.5vw, 0.5vh);*/ flex-basis:32px; } .Experience_AC_Play > button { width:62px; height:62px; border-radius: 100px; background-color: rgba(30, 30, 150, 1.0); cursor:pointer; color:#fff; transition:background-color 0.5s; pointer-events:all; } .Experience_AC_Play > button:hover { background-color: rgb(49, 49, 255); } .Experience_AC_Songs { flex: 3 0 10%; /* margin:max(0.5vw, 0.5vh);*/ position:relative; /* top:6px;*/ /* flex-basis:176px;*/ flex-basis:32px; } .Experience_AC_Songs > select { position:relative; left:5px; height: 22px; pointer-events:all; } .Experience_AC_Volume { flex-basis:32px; /* margin:max(0.5vw, 0.5vh);*/ /* flex-basis:150px;*/ } .Experience_AC_Volume > input { position:relative; left:5px; top:5px; pointer-events:all; } .Experience_AC_Time { flex-basis:32px; /* margin:max(0.5vw, 0.5vh);*/ } .Experience_AC_Time > input { position:relative; left:5px; top:5px; width: calc(100% - 10px); pointer-events:all; } .Experience td { color:#ffffff; text-shadow: 1px 1px #000000; } /* Pay & Pause buttons */ .Experience_Play, .Experience_Pause { position: fixed; margin-bottom: max(0.5vw, 0.5vh); margin-left: max(0.5vw, 0.5vh); bottom:0; } /* when play is true, play button is enabled, and pause button is disabled, when is false is the oposite */ .Experience_Play[play="false"], .Experience_Pause[play="true"] { display:none; } .Experience_SongInfo { position:fixed; margin-bottom: max(0.5vw, 0.5vh); margin-left: max(0.5vw, 0.5vh); bottom:70px; padding:12px; left:-500px; transition:left 0.4s cubic-bezier(.17,-0.42,0,1.15); } .Experience_SongInfo[visible="false"] { left:0px; animation: SongInfoAnimation 0.4s 5s cubic-bezier(.17,-0.42,0,1.15); animation-fill-mode:forwards; } .Experience_SongInfo td { padding: 4px; color:#CCCCCC; } .Experience_SongInfo a, .Experience_SongInfo a:visited { color:#FFFFFF; } @keyframes SongInfoAnimation { 0% { opacity:1; left:0px; } 100% { opacity:0; left:-300px; } } </style> </head> <body > <!-- import THREE.js cdn --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/es-module-shims.1.6.2.js"></script> <script type="importmap"> { "imports": { "three": "//repo.bfw.wiki/bfwrepo/js/module/three/build/151/three.module.js", "three/addons/": "//repo.bfw.wiki/bfwrepo/js/module/three/examples/151/jsm/" } } </script> <!-- Bars vertex shader--> <script id="BarsVertexShader" type="x-shader/x-vertex"> uniform sampler2D uAudioTexture; // Linear texture (1024 * 1) to get audio values uniform float uAudioStrength; // Strength multiplyer attribute float aId; // Its an unique ID for each bar (1.0 / totalBars * actualBar) varying vec2 vUv; void main() { vec4 modelPosition = modelMatrix * vec4(position , 1.0); // If the point is from superior part vec4 data = texture2D(uAudioTexture, vec2(aId, 0.0)); if (uv.y > 0.1) { // Add the red channel intensity to the Y of the model modelPosition.y += data.r * uAudioStrength; } else { modelPosition.y -= data.r * uAudioStrength; } vec4 viewPosition = viewMatrix * modelPosition; vec4 projectionPosition = projectionMatrix * viewPosition; gl_Position = projectionPosition; vUv = uv; } </script> <!-- Bars fragment shader--> <script id="BarsFragmentShader" type="x-shader/x-fragment"> varying vec2 vUv; void main() { float dist = length(vUv - vec2(0.5)); // Fill the bar with red gl_FragColor = vec4(0.75 + dist, 1.0 - dist, 0.0, 1.0); } </script> <!-- Bars Depth vertex shader--> <script id="BarsDepthVertexShader" type="x-shader/x-vertex"> uniform sampler2D uAudioTexture; // Linear texture (1024 * 1) to get audio values uniform float uAudioStrength; // Strength multiplyer attribute float aId; // Its an unique ID for each bar (1.0 / totalBars * actualBar) #include <common> #include <uv_pars_vertex> #include <displacementmap_pars_vertex> #include <morphtarget_pars_vertex> #include <skinning_pars_vertex> #include <logdepthbuf_pars_vertex> #include <clipping_planes_pars_vertex> varying vec2 vHighPrecisionZW; void main() { #include <uv_vertex> #include <skinbase_vertex> #ifdef USE_DISPLACEMENTMAP #include <beginnormal_vertex> #include <morphnormal_vertex> #include <skinnormal_vertex> #endif #include <begin_vertex> //vec4 audioValue = vec4(1.0); vec4 audioValue = texture2D(uAudioTexture, vec2(aId, 0.0)); if (uv.y > 0.5) { // Add the red channel intensity to the Y of the model transformed.y += audioValue.r * uAudioStrength; } else { transformed.y -= audioValue.r * uAudioStrength; } #include <morphtarget_vertex> #include <skinning_vertex> #include <displacementmap_vertex> #include <project_vertex> #include <logdepthbuf_vertex> #include <clipping_planes_vertex> vHighPrecisionZW = gl_Position.zw; } </script> <!-- Floor Standard vertex shader--> <script id="FloorStandardVertexShader" type="x-shader/x-vertex"> uniform sampler2D uAudioTexture; //uniform float uTime; uniform float uAudioStrength; varying vec2 vUv; /* * Three.js globals */ #define STANDARD varying vec3 vViewPosition; #ifdef USE_TRANSMISSION varying vec3 vWorldPosition; #endif #include <common> #include <uv_pars_vertex> #include <displacementmap_pars_vertex> #include <color_pars_vertex> #include <fog_pars_vertex> #include <normal_pars_vertex> #include <morphtarget_pars_vertex> #include <skinning_pars_vertex> #include <shadowmap_pars_vertex> #include <logdepthbuf_pars_vertex> #include <clipping_planes_pars_vertex> /* * Three.js main */ void main() { #include <uv_vertex> #include <color_vertex> #include <morphcolor_vertex> #include <beginnormal_vertex> #include <morphnormal_vertex> #include <skinbase_vertex> #include <skinnormal_vertex> #include <defaultnormal_vertex> #include <normal_vertex> #include <begin_vertex> // Audio value on Y axis vec4 textureColor = texture2D(uAudioTexture, uv); transformed.z += textureColor.r * uAudioStrength; vUv = uv; /* * Three.js main end */ #include <morphtarget_vertex> #include <skinning_vertex> #include <displacementmap_vertex> #include <project_vertex> #include <logdepthbuf_vertex> #include <clipping_planes_vertex> vViewPosition = - mvPosition.xyz; #include <worldpos_vertex> #include <shadowmap_vertex> #include <fog_vertex> #ifdef USE_TRANSMISSION vWorldPosition = worldPosition.xyz; #endif } </script> <!-- Floor Depth vertex shader--> <script id="FloorDepthVertexShader" type="x-shader/x-vertex"> uniform sampler2D uAudioTexture; uniform float uAudioStrength; #include <common> #include <uv_pars_vertex> #include <displacementmap_pars_vertex> #include <morphtarget_pars_vertex> #include <skinning_pars_vertex> #include <logdepthbuf_pars_vertex> #include <clipping_planes_pars_vertex> varying vec2 vHighPrecisionZW; void main() { #include <uv_vertex> #include <skinbase_vertex> #ifdef USE_DISPLACEMENTMAP #include <beginnormal_vertex> #include <morphnormal_vertex> #include <skinnormal_vertex> #endif #include <begin_vertex> //vec4 audioValue = vec4(1.0); vec4 audioValue = texture2D(uAudioTexture, uv); if (uv.y > 0.5) { // Add the red channel intensity to the Y of the model transformed.y += audioValue.r * uAudioStrength; } else { transformed.y -= audioValue.r * uAudioStrength; } #include <morphtarget_vertex> #include <skinning_vertex> #include <displacementmap_vertex> #include <project_vertex> #include <logdepthbuf_vertex> #include <clipping_planes_vertex> vHighPrecisionZW = gl_Position.zw; } </script> <script type="module"> /* Experience created by Josep Antoni Bover for https://devildrey33.es. * This Audio shader is a part of my Audio-PlayGround experience : * https://github.com/devildrey33/Audio-PlayGround * * #7 Floor and bars effect. * - Play with Audio Strength, Line size, and radius to achieve different effects * - This script creates an audio data texture with the getByteTimeFrequency values * on the red channel and the getByteTimeByDomain on the green channel. (Its more easy than creating extra attributes, and looks better) * - Then this texture is sent to the sunset shader and the sunset depth shader. * - You can drag & drop any song of your computer to play it. * - Song name : Alone * Song artist : Color Out * URL : https://www.jamendo.com/track/1886257/alone * * Created on : 16/05/2023 * Last modification : 16/05/2023 */ import { OrbitControls } from 'three/addons/controls/OrbitControls.js' import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js' import * as THREE from 'three' // Simple 2d buffer canvas class BufferCanvas { constructor(width, height) { this.canvas = document.createElement("canvas"); this.canvas.setAttribute("width", width); this.canvas.setAttribute("height", height); this.context = this.canvas.getContext("2d", { willReadFrequently : true }); this.width = width; this.height = height; } } export default class CodepenThreeAudio { // Default options options = { // Y position. Use 'auto' to center canvas horizontaly to the view port top : 0, // X position. Use 'auto' to center canvas verticaly to the view port left : 0, // Width in pixels. Use 'auto' to fit all viewport width width : "auto", // Height in pixels. Use 'auto' to fit all viewport height height : "auto", // Show framerate inside the butons frame showFPS : true, // Show full screen buton in the buttons frame buttonFullScreen : true, // Show my logo buton in the buttons frame (that redirects to devildrey33.es) buttonLogo : true, // Show a github icon to go to the example repository buttonGitHub : true, // GitHub url for this project (only used if buttonGitHub is true) urlGitHub : "https://github.com/devildrey33/Audio-PlayGround", // Element where canvas is inserted (by default is document.body) // For example you can use document.getElementById() to retrieve tag inside you want to create the canvas rootElement : document.body, // Anti alias (by default true) antialias : true, // OrbitControls enabled by default orbitControls : true, // Song path songPath : "//repo.bfw.wiki/bfwrepo/sound/5e148aa3821f2.mp3" }; constructor(options) { // Merge options this.options = { ...this.options, ...options }; // Create basic html elements this.createHtml(); // Setup sizes this.setupSizes(); // Setup audio fft size this.fftSize = 2048; this.square = Math.sqrt(this.fftSize * 0.5); // Setup audio texture this.bufferCanvasLinear = new BufferCanvas(1024, 1); this.bufferCanvasLinear.texture = new THREE.CanvasTexture(this.bufferCanvasLinear.canvas); this.imageDataLinear = this.bufferCanvasLinear.context.createImageData(1024, 1); this.bufferCanvasLinear.texture.generateMipMaps = false; this.bufferCanvasLinear.texture.minFilter = THREE.NearestFilter; this.bufferCanvasLinear.texture.magFilter = THREE.NearestFilter; this.bufferCanvasSquare = new BufferCanvas(this.square, this.square); this.bufferCanvasSquare.texture = new THREE.CanvasTexture(this.bufferCanvasSquare.canvas); this.bufferCanvasSquare.texture.minFilter = THREE.NearestFilter; this.bufferCanvasSquare.texture.magFilter = THREE.NearestFilter; this.imageDataSquare = this.bufferCanvasSquare.context.createImageData(this.square, this.square); // Setup buffers for audio data this.analizerData = new Uint8Array(this.fftSize * 0.5); this.analizerDataSin = new Uint8Array(this.fftSize * 0.5); // Fill the sin array with 128, because its the central point for (let i = 0; i < this.fftSize * 0.5; i++) { this.analizerDataSin[i] = 128; } // Setup a basic scene with camera this.setupBasicScene(); // Time values this.timeStart = Date.now(); this.timeCurrent = this.timeStart; this.timeElapsed = 0; this.timeDelta = 16; // Time from this second this.timeActualFrame = this.timeStart + 1000; // Number of frames during this second this.timeFrameCounter = 0; // actual framerate this.fps = 0; // Drag & drop events this.hEventDragEnter = this.eventDragEnter.bind(this); this.hEventDragOver = this.eventDragOver.bind(this); this.hEventDrop = this.eventDrop.bind(this); this.elementCanvas.addEventListener("dragenter", this.hEventDragEnter); this.elementCanvas.addEventListener("dragover" , this.hEventDragOver); this.elementCanvas.addEventListener("drop" , this.hEventDrop); // song loaded this.songLoaded = false; // default song true (not a drag & drop song) this.defaultSong = true; // Setup a Three.js renderer this.setupRenderer(); // Create the update loop window.requestAnimationFrame(() => { this.basicUpdate(); }); } /* * Create basic html elements (canvas, loading, framerate, fullscreen, github, and my web page button) */ createHtml() { // Create an empty div element outside of the doom, to make it our root element const preElementExperience = document.createElement("div"); // Id of this canvas (i need it for compatibility with my web page) this.id = 0; preElementExperience.id = "Experience" + this.id; preElementExperience.className = "Experience"; // Add the Experience element to the options root element this.options.rootElement.appendChild(preElementExperience); this.elementExperience = document.getElementById(preElementExperience.id); // Setup the loading atribute this.elementExperience.setAttribute("loading", true); // String that has all the tags to be added let strHTML = "" // Add the canvas element strHTML += '<canvas id="Experience' + this.id + '_Canvas" class="Experience_Canvas"></canvas>'; // Add the loading element strHTML += '<div class="Experience_Loading Experience_Panel"><span>Loading...</span></div>'; // Add the main controls element strHTML += '<div class="Experience_Controls">'; // Show FPS if (this.options.showFPS === true) { strHTML += "<div class='Experience_Panel Experience_Static' title='Frames Per Second'>" + "<div class='Experience_FPS'>60</div>" + "<div class='Experience_TxtFPS'>fps</div>" + "</div>"; } // Show full screen button if (this.options.buttonFullScreen === true) { strHTML += "<div id='fullScreen' class='Experience_Panel Experience_Control' title='Full screen mode'>" + "<img draggable='false' src='https://devildrey33.es/Ejemplos/Three.js-Journey/Audio-PlayGround/icos.svg#svg-pantalla-completa' />" + "</div>" + "<div id='restoreScreen' class='Experience_Panel Experience_Control' title='Restore screen'>" + "<img draggable='false' src='https://devildrey33.es/Ejemplos/Three.js-Journey/Audio-PlayGround/icos.svg#svg-restaurar-pantalla' />" + "</div>"; } // Closing .Experience_Controls strHTML += '</div>'; // Play button strHTML += '<div class=&quo.........完整代码请登录后点击上方下载按钮下载查看
网友评论0