What’s on our mind?

Collection of articles, design, site, and resources made by designers and publisher @Menu View

* index10
var settings = {
    numParticles: 180,
    opacityDecay: 0.20,
};

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");

function fill(rgb, amt) {
    ctx.beginPath();
    ctx.rect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
    ctx.fillStyle = "rgba(" + [...rgb, amt] + ")";
    ctx.fill();
}

function drawCircle(x, y, radius, color) {
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, 2 * Math.PI);
    ctx.fillStyle = color || 'white';
    ctx.fill();
    ctx.closePath();
}

document.getElementsByTagName("body")[0].appendChild(canvas);

var bg = [20, 0, 30]
var wh = window.innerHeight

function setup() {
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    wh = window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight
    ctx.translate(canvas.width / 2, canvas.height / 2)
    fill(bg, 1)
}

var particles = [];
for (var i = 0; i < settings.numParticles; i++) {
    particles.push(new Particle());
}

function draw() {
    fill(bg, settings.opacityDecay)

    for (var i = 0; i < particles.length; i++) {
        particles[i].draw() // do it once
    }

    window.requestAnimationFrame(function () {
        draw()
    })
}

setup()
draw();

window.addEventListener("resize", setup)

function Particle() {
    this.loop1 = new Looper(500 + 200 * Math.random(), 700 * Math.random());
    this.loop2 = new Looper(790 + 170 * Math.random(), 80 * Math.random());
    this.loop3 = new Looper(120 + 20 * Math.random(), 140 * Math.random());
    this.loop1.update();
    this.loop2.update();
    this.loop3.update();
    this.history = [];
    this.history_max = 5;
    this.offset = Math.random(); 

    this.draw = function () {
        var x = this.loop1.sin * 0.25 + this.loop2.sin * 0.17 + this.loop3.sin * 0.09;
        var y = this.loop1.cos * 0.25 + this.loop2.cos * 0.5 + this.loop3.cos * 0.02;
        var r = 0.2 + 3 * this.loop3.sinNorm * this.loop3.cosNorm; // set the radius
        var hsla = [
            70 - 40 * (this.loop3.cosNorm + this.offset) * this.loop2.sinNorm,
            100 + "%",
            (50 + 10 * this.loop3.sin) + "%",
            1
        ];
        var c = "hsla(" + [...hsla] + ")";

        ctx.beginPath();
        ctx.strokeStyle = c;
        ctx.lineCap = 'round';
        ctx.lineWidth = r * 2;
        var tx = x * wh
        var ty = y * wh
        for (var i = 0; i < Math.min(this.history_max * this.loop3.cosNorm, this.history.length); i++) {
            ctx.moveTo(tx, ty);
            tx = this.history[i][0] * wh;
            ty = this.history[i][1] * wh;
            ctx.lineTo(tx, ty);
        }
        ctx.stroke();

        this.history.unshift([x, y]);
        while (this.history.length > this.history_max) {
            this.history.pop();
        }

        drawCircle(x * wh, y * wh, r * 2 + 3, c); // draw the circle

        this.loop1.update(); // update looper 1
        this.loop2.update(); // update looper 2
        this.loop3.update(); // update looper 3
    }
}

function Looper(steps, start) {
    this.val = start || 0; 
    this.steps = steps || 100;

    this.update = function () {
        this.val = (this.val + 1) % this.steps; 
        this.norm = this.val / this.steps;
        this.sin = Math.sin(this.norm * Math.PI * 2);
        this.sinNorm = (this.sin + 1) / 2; 
        this.cos = Math.cos(this.norm * Math.PI * 2); 
        this.cosNorm = (this.cos + 1) / 2;
    }

    this.update();
}