Skip to content

Instantly share code, notes, and snippets.

@scottdomes
Created September 18, 2017 21:35
Show Gist options
  • Save scottdomes/aae01cce0fdb69cea49aa5b3b75f3313 to your computer and use it in GitHub Desktop.
Save scottdomes/aae01cce0fdb69cea49aa5b3b75f3313 to your computer and use it in GitHub Desktop.

Revisions

  1. scottdomes created this gist Sep 18, 2017.
    92 changes: 92 additions & 0 deletions app.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    body {
    background: #f9f9f9;
    font-family: 'Open Sans', sans-serif;
    text-align: center;
    }

    #container {
    position: relative;
    z-index: 2;
    padding-top: 100px;
    }

    .play {
    display: block;
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-bottom: 50px solid transparent;
    border-left: 60px solid #2c3e50;
    margin: 100px auto 50px auto;
    position: relative;
    z-index: 1;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    left: 10px;
    }

    .play:before {
    content: '';
    position: absolute;
    top: -75px;
    left: -115px;
    bottom: -75px;
    right: -35px;
    border-radius: 50%;
    border: 10px solid #2c3e50;
    z-index: 2;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    }
    .play:after {
    content: '';
    opacity: 0;
    transition: opacity 0.6s;
    -webkit-transition: opacity 0.6s;
    -moz-transition: opacity 0.6s;
    }
    .play:hover:before, .play:focus:before {
    transform: scale(1.1);
    -webkit-transform: scale(1.1);
    -moz-transform: scale(1.1);
    }
    .play.active {
    border-color: transparent;
    }
    .play.active:after {
    content: '';
    opacity: 1;
    width: 25px;
    height: 80px;
    position: absolute;
    right: 8px;
    top: -40px;
    border-right: 20px solid #2c3e50;
    border-left: 20px solid #2c3e50;
    }

    h1 {
    text-transform: uppercase;
    color: #34495e;
    letter-spacing: 2px;
    font-size: 2em;
    margin-bottom: 0;
    }

    canvas {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    }

    audio {
    position: fixed;
    left: 10px;
    bottom: 10px;
    width: calc(100% - 20px);
    }

    267 changes: 267 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,267 @@
    var ALPHA,
    AudioAnalyser,
    COLORS,
    MP3_PATH,
    NUM_BANDS,
    NUM_PARTICLES,
    Particle,
    SCALE,
    SIZE,
    SMOOTHING,
    SPEED,
    SPIN,
    TIMES_CALLED,
    ANALYSER;

    NUM_PARTICLES = 150;

    NUM_BANDS = 128;

    TIMES_CALLED = 0;

    SMOOTHING = 0.5;

    MP3_PATH = 'music.mp3';

    SCALE = {
    MIN: 5.0,
    MAX: 80.0
    };

    SPEED = {
    MIN: 0.2,
    MAX: 1.0
    };

    ALPHA = {
    MIN: 0.8,
    MAX: 0.9
    };

    SPIN = {
    MIN: 0.001,
    MAX: 0.005
    };

    SIZE = {
    MIN: 0.5,
    MAX: 1.25
    };

    COLORS = [
    '#69D2E7',
    '#1B676B',
    '#BEF202',
    '#EBE54D',
    '#00CDAC',
    '#1693A5',
    '#F9D423',
    '#FF4E50',
    '#E7204E',
    '#0CCABA',
    '#FF006F'
    ];
    function getAnimation(file) {
    AudioAnalyser = (function() {
    AudioAnalyser.AudioContext = self.AudioContext || self.webkitAudioContext;

    AudioAnalyser.enabled = AudioAnalyser.AudioContext != null;

    function AudioAnalyser(audio, numBands, smoothing) {
    var src;
    this.audio = audio != null ? audio : new Audio();
    this.numBands = numBands != null ? numBands : 256;
    this.smoothing = smoothing != null ? smoothing : 0.3;
    this.audio = document.getElementById('audio');
    if (!this.audio) {
    return;
    }
    try {
    this.audio.src = window.URL.createObjectURL(file);
    } catch (err) {
    console.log(err);
    }
    this.context = new AudioAnalyser.AudioContext();
    this.jsNode = this.context.createScriptProcessor(2048, 1, 1);
    this.analyser = this.context.createAnalyser();
    this.analyser.smoothingTimeConstant = this.smoothing;
    this.analyser.fftSize = this.numBands * 2;
    this.bands = new Uint8Array(this.analyser.frequencyBinCount);
    this.audio.addEventListener(
    'play',
    (function(_this) {
    return function() {
    if (TIMES_CALLED === 1) {
    return;
    }
    ANALYSER.start();
    TIMES_CALLED++;
    _this.source = _this.context.createMediaElementSource(_this.audio);
    _this.source.connect(_this.analyser);
    _this.analyser.connect(_this.jsNode);
    _this.jsNode.connect(_this.context.destination);
    _this.source.connect(_this.context.destination);
    return (_this.jsNode.onaudioprocess = function() {
    _this.analyser.getByteFrequencyData(_this.bands);
    if (!_this.audio.paused) {
    return typeof _this.onUpdate === 'function'
    ? _this.onUpdate(_this.bands)
    : void 0;
    }
    });
    };
    })(this)
    );
    }

    AudioAnalyser.prototype.start = function() {
    return this.audio.play();
    };

    AudioAnalyser.prototype.stop = function() {
    return this.audio.pause();
    };

    return AudioAnalyser;
    })();

    Particle = (function() {
    function Particle(x1, y1) {
    this.x = x1 != null ? x1 : 0;
    this.y = y1 != null ? y1 : 0;
    this.reset();
    }

    Particle.prototype.reset = function() {
    this.level = 1 + floor(random(4));
    this.scale = random(SCALE.MIN, SCALE.MAX);
    this.alpha = random(ALPHA.MIN, ALPHA.MAX);
    this.speed = random(SPEED.MIN, SPEED.MAX);
    this.color = random(COLORS);
    this.size = random(SIZE.MIN, SIZE.MAX);
    this.spin = random(SPIN.MAX, SPIN.MAX);
    this.band = floor(random(NUM_BANDS));
    if (random() < 0.5) {
    this.spin = -this.spin;
    }
    this.smoothedScale = 0.0;
    this.smoothedAlpha = 0.0;
    this.decayScale = 0.0;
    this.decayAlpha = 0.0;
    this.rotation = random(TWO_PI);
    return (this.energy = 0.0);
    };

    Particle.prototype.move = function() {
    this.rotation += this.spin;
    return (this.y -= this.speed * this.level);
    };

    Particle.prototype.draw = function(ctx) {
    var alpha, power, scale;
    power = exp(this.energy);
    scale = this.scale * power;
    alpha = this.alpha * this.energy * 1.5;
    this.decayScale = max(this.decayScale, scale);
    this.decayAlpha = max(this.decayAlpha, alpha);
    this.smoothedScale += (this.decayScale - this.smoothedScale) * 0.3;
    this.smoothedAlpha += (this.decayAlpha - this.smoothedAlpha) * 0.3;
    this.decayScale *= 0.985;
    this.decayAlpha *= 0.975;
    ctx.save();
    ctx.beginPath();
    ctx.translate(this.x + cos(this.rotation * this.speed) * 250, this.y);
    ctx.rotate(this.rotation);
    ctx.scale(
    this.smoothedScale * this.level,
    this.smoothedScale * this.level
    );
    ctx.moveTo(this.size * 0.5, 0);
    ctx.lineTo(this.size * -0.5, 0);
    ctx.lineWidth = 1;
    ctx.lineCap = 'round';
    ctx.globalAlpha = this.smoothedAlpha / this.level;
    ctx.strokeStyle = this.color;
    ctx.stroke();
    return ctx.restore();
    };

    return Particle;
    })();

    Sketch.create({
    particles: [],
    setup: function() {
    var analyser, error, i, intro, j, particle, ref, warning, x, y;
    for (i = j = 0, ref = NUM_PARTICLES - 1; j <= ref; i = j += 1) {
    x = random(this.width);
    y = random(this.height * 2);
    particle = new Particle(x, y);
    particle.energy = random(particle.band / 256);
    this.particles.push(particle);
    }
    if (AudioAnalyser.enabled) {
    try {
    analyser = new AudioAnalyser(MP3_PATH, NUM_BANDS, SMOOTHING);
    analyser.onUpdate = (function(_this) {
    return function(bands) {
    var k, len, ref1, results;
    ref1 = _this.particles;
    results = [];
    for (k = 0, len = ref1.length; k < len; k++) {
    particle = ref1[k];
    results.push((particle.energy = bands[particle.band] / 256));
    }
    return results;
    };
    })(this);
    analyser.audio = window.audio;
    ANALYSER = analyser;
    intro = document.getElementById('intro');
    intro.style.display = 'none';
    if (
    /Safari/.test(navigator.userAgent) &&
    !/Chrome/.test(navigator.userAgent)
    ) {
    warning = document.getElementById('warning2');
    return (warning.style.display = 'block');
    }
    } catch (_error) {
    error = _error;
    }
    } else {
    warning = document.getElementById('warning1');
    return (warning.style.display = 'block');
    }
    },
    draw: function() {
    var j, len, particle, ref, results;
    this.globalCompositeOperation = 'lighter';
    ref = this.particles;
    results = [];
    for (j = 0, len = ref.length; j < len; j++) {
    particle = ref[j];
    if (particle.y < -particle.size * particle.level * particle.scale * 2) {
    particle.reset();
    particle.x = random(this.width);
    particle.y =
    this.height + particle.size * particle.scale * particle.level;
    }
    particle.move();
    results.push(particle.draw(this));
    }
    return results;
    }
    });
    }

    function handleFileSelect(evt) {
    var files = evt.target.files;
    getAnimation(files[0]);
    }

    getAnimation(null);

    document
    .getElementById('files')
    .addEventListener('change', handleFileSelect, false);
    15 changes: 15 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    <link rel="stylesheet" href="app.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,800">
    <div id="container">
    <div id="hook"></div>
    <h1>Play Music</h1>
    <input type="file" id="files" name="files[]" multiple />
    </div>
    <script crossorigin src="https://unpkg.com/react@15/dist/react.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
    <script src="https://npmcdn.com/[email protected]/browser.min.js"></script>
    <script src="https://soulwire.github.io/sketch.js/js/sketch.min.js"></script>
    <script src="app.js"></script>
    <script type="text/babel">
    // React code goes here.
    </script>