This repository has been archived on 2022-09-16. You can view files and clone it, but cannot push or open issues/pull-requests.
tlaternet-templates/src/music/player/backgrounds/Spectrum.js

136 lines
3.6 KiB
JavaScript

import $ from "jquery";
import * as three from "three";
import Background from "../background";
class Spectrum extends Background {
constructor(display, audioManager) {
super(audioManager, display);
this._audioManager = audioManager;
this._display = display;
this._init_analyser();
this._init_scene();
this._init_objects();
this._resize();
}
_get_canvas_height() {
return (
this._display.parent().height() -
this._display
.siblings()
.toArray()
.reduce((a, b) => {
return a + b.clientHeight;
}, 0)
);
}
_resize() {
this._camera.aspect = this._display.width() / this._get_canvas_height();
this._camera.updateProjectionMatrix();
this._renderer.setSize(
this._display.width(),
this._get_canvas_height()
);
}
_init_analyser() {
let audioManager = this._audioManager;
let analyser = audioManager.context.createAnalyser();
analyser.fftSize = 2048;
analyser.smoothingTimeConstant = 0.8;
let analyser_data = new Float32Array(analyser.frequencyBinCount);
audioManager.source.connect(analyser);
analyser.getFloatFrequencyData(analyser_data);
this._analyser = analyser;
this._analyser_data = analyser_data;
}
_init_scene() {
let scene = new three.Scene();
let camera = new three.PerspectiveCamera(
70,
this._display.width() / this._get_canvas_height(),
0.01,
10
);
camera.position.z = 1;
scene.add(camera);
let renderer = new three.WebGLRenderer({
antialias: true,
powerPreference: "low-power"
});
renderer.setSize(this._display.width(), this._display.height());
this._display.append(renderer.domElement);
this._scene = scene;
this._camera = camera;
this._renderer = renderer;
// Set the resize handler
$(window).resize(() => this._resize());
}
_init_objects() {
let analyser = this._analyser;
let scene = this._scene;
let boxes = Array(analyser.frequencyBinCount);
let width = 2 / analyser.frequencyBinCount;
for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
let geometry = new three.BoxGeometry(1, 1, 1);
let material = new three.MeshBasicMaterial({ color: 0x99d1ce });
let cube = new three.Mesh(geometry, material);
cube.scale.set(width, 1e-6, width);
cube.position.set(-1 + freq * width, 0, 0);
scene.add(cube);
boxes[freq] = cube;
}
this._boxes = boxes;
}
start() {
requestAnimationFrame(this._render.bind(this));
}
_render() {
let analyser = this._analyser;
let camera = this._camera;
let renderer = this._renderer;
let scene = this._scene;
for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
let height = analyser.maxDecibels / this._analyser_data[freq];
if (height > 0.3) {
height -= 0.3;
} else {
height = 1e-6;
}
this._boxes[freq].scale.y = height;
}
renderer.render(scene, camera);
analyser.getFloatFrequencyData(this._analyser_data);
requestAnimationFrame(this._render.bind(this));
}
}
export default Spectrum;