akko
Version:
Music visualising framework based on WebGL and Web Audio API.
133 lines (112 loc) • 3.78 kB
JavaScript
/**
* @author Timur Kuzhagaliyev <tim.kuzh@gmail.com>
* @copyright 2017
* @license GPL-3.0
*/
const THREE = require('three');
const MusicPlayer = require('./MusicPlayer');
const VisualisationCore = require('./VisualisationCore');
const UI = require('./UI.jsx');
/**
* @type {{containerId: string, useDefaultVisualisers: boolean, autoPlay: boolean}}
*/
const defaultOptions = {
containerId: 'akko',
useDefaultVisualisers: true,
autoPlay: false,
};
/**
* @return {{containerId: string, useDefaultVisualisers: boolean, autoPlay: boolean}}
*/
const mergeOptions = (options = {}) => {
let result = {};
for (let key in defaultOptions) {
if (!defaultOptions.hasOwnProperty(key)) continue;
result[key] = options[key] !== undefined ? options[key] : defaultOptions[key];
}
return result;
};
class Akko {
constructor(options) {
if (!THREE) throw new Error('Akko could not find three.js (`THREE`)!');
if (!window) throw new Error('Akko could not find `window` variable! Are you running Akko in browser?');
if (!document) throw new Error('Akko could not find `document` variable! Are you running Akko in browser?');
this.AudioContext = window.AudioContext || window.webkitAudioContext;
if (!this.AudioContext) throw new Error('Akko could not find `AudioContext`! Is it supported in your browser?');
this.options = mergeOptions(options);
this.container = document.getElementById(this.options.containerId);
if (!this.container) throw new Error(`Could not find element with ID '${this.options.containerId}'!`);
this.musicPlayer = new MusicPlayer({
audioContext: new this.AudioContext(),
autoPlay: options.autoPlay,
});
this.visCore = new VisualisationCore({
parentElement: this.container,
useDefaultVisualisers: this.options.useDefaultVisualisers,
analyser: this.musicPlayer.getAnalyser(),
});
}
start() {
this.bootstrapUI();
this.visCore.prepare();
this.visCore.useVisualiser(0);
this.musicPlayer.start();
this.visCore.start();
this.setupListeners();
}
bootstrapUI() {
this.ui = new UI({
container: this.container,
musicPlayer: this.musicPlayer,
visCore: this.visCore,
});
this.ui.start();
}
/**
* @param {Visualiser} visualiser
*/
addVisualiser(visualiser) {
this.visCore.addVisualiser(visualiser);
}
/**
* @param {string|File|ArrayBuffer} source
* @param {string} [title]
*/
addTrack(source, title) {
this.musicPlayer.addTrack(source, title);
}
/**
* @private
*/
setupListeners() {
if (window.File && window.FileReader && window.FileList && window.Blob) {
this.container.addEventListener('dragover', this.onDragOver.bind(this), false);
this.container.addEventListener('drop', this.onDrop.bind(this), false);
} else {
console.warn('The File APIs are not fully supported your browser. Drag & drop disabled in Akko.');
}
}
/**
* @private
*/
onDragOver(event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}
/**
* @private
*/
onDrop(event) {
event.stopPropagation();
event.preventDefault();
let files = event.dataTransfer.files;
for (let i = 0; i < files.length; i++) {
let file = files[i];
if (file.type.match(/audio.*/)) {
this.musicPlayer.addTrack(file);
}
}
}
}
module.exports = Akko;