Lightning

http://jsdo.it/akm2/pQbMLightning Points (Lightning 2) http://codepen.io/akm2/pen/LuDba

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>Lightning</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>
  <canvas id='c'></canvas>
  <script src='https://rawgit.com/akm2/simplex-noise.js/master/simplex-noise.js'></script>
<script src='js/kzymdn.js'></script>

    <script  src="js/index.js"></script>

</body>
</html>
/* Downloaded from https://www.codeseek.co/ */
body {
    font-family: sans-serif;
    padding: 0;
    margin: 0;
    background-color: #222;
    overflow: hidden;
    -webkit-user-select: none;
       -moz-user-select: none;
         -o-user-select: none;
        -ms-user-select: none;
            user-select: none;
}

canvas {
    position: absolute;
    top: 0;
    left: 0;
}
/* Downloaded from https://www.codeseek.co/ */
/**
 * requestAnimationFrame
 */
window.requestAnimationFrame = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.oRequestAnimationFrame      ||
            window.msRequestAnimationFrame     ||
            function (callback) {
                window.setTimeout(callback, 1000 / 60);
            };
})();


/**
 * Vector
 */
function Vector(x, y) {
    this.x = x || 0;
    this.y = y || 0;
}

Vector.add = function(a, b) {
    return new Vector(a.x + b.x, a.y + b.y);
};

Vector.sub = function(a, b) {
    return new Vector(a.x - b.x, a.y - b.y);
};

Vector.prototype = {
    set: function(x, y) {
        if (typeof x === 'object') {
            y = x.y;
            x = x.x;
        }
        this.x = x || 0;
        this.y = y || 0;
        return this;
    },

    add: function(v) {
        this.x += v.x;
        this.y += v.y;
        return this;
    },

    sub: function(v) {
        this.x -= v.x;
        this.y -= v.y;
        return this;
    },

    scale: function(s) {
        this.x *= s;
        this.y *= s;
        return this;
    },

    length: function() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },

    normalize: function() {
        var len = Math.sqrt(this.x * this.x + this.y * this.y);
        if (len) {
            this.x /= len;
            this.y /= len;
        }
        return this;
    },

    angle: function() {
        return Math.atan2(this.y, this.x);
    },

    distanceTo: function(v) {
        var dx = v.x - this.x,
            dy = v.y - this.y;
        return Math.sqrt(dx * dx + dy * dy);
    },

    distanceToSq: function(v) {
        var dx = v.x - this.x,
            dy = v.y - this.y;
        return dx * dx + dy * dy;
    },

    clone: function() {
        return new Vector(this.x, this.y);
    }
};


/**
 * Point
 */
function Point(x, y, radius) {
    Vector.call(this, x, y);

    this.radius = radius || 7;

    this.vec = new Vector(random(1, -1), random(1, -1)).normalize();
    this._easeRadius    = this.radius;
    this._currentRadius = this.radius;

}

Point.prototype = (function(o) {
    var s = new Vector(0, 0), p;
    for (p in o) {
        s[p] = o[p];
    }
    return s;
})({
    color:       'rgb(255, 255, 255)',
    dragging:    false,
    _latestDrag: null,

    update: function(points, bounds) {
        this._currentRadius = random(this._easeRadius, this._easeRadius * 0.35);
        this._easeRadius += (this.radius - this._easeRadius) * 0.1;

        if (this.dragging) return;

        var vec = this.vec,
            i, len, p, d;

        for (i = 0, len = points.length; i < len; i++) {
            p = points[i];
            if (p !== this) {
                d = this.distanceToSq(p);
                if (d < 90000) {
                    vec.add(Vector.sub(this, p).normalize().scale(0.03));
                } else if (d > 250000) {
                    vec.add(Vector.sub(p, this).normalize().scale(0.015));
                }
            }
        }

        if (vec.length() > 3) vec.normalize().scale(3);

        this.add(vec);

        if (this.x < bounds.x) {
            this.x = bounds.x;
            if (vec.x < 0) vec.x *= -1;

        } else if (this.x > bounds.right) {
            this.x = bounds.right;
            if (vec.x > 0) vec.x *= -1;
        }

        if (this.y < bounds.y) {
            this.y = bounds.y;
            if (vec.y < 0) vec.y *= -1;

        } else if (this.y > bounds.bottom) {
            this.y = bounds.bottom;
            if (vec.y > 0) vec.y *= -1;
        }
    },

    hitTest: function(p) {
        if (this.distanceToSq(p) < 900) {
            this._easeRadius = this.radius * 2.5;
            return true;
        }
        return false;
    },

    startDrag: function() {
        this.dragging = true;
        this.vec.set(0, 0);
        this._latestDrag = new Vector().set(this);
    },

    drag: function(p) {
        this._latestDrag.set(this);
        this.set(p);
    },

    endDrag: function() {
        this.vec = Vector.sub(this, this._latestDrag);
        this.dragging = false;
    },

    draw: function(ctx) {
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this._currentRadius, 0, Math.PI * 2, false);
        ctx.fill();
        ctx.shadowBlur  = 20;
        ctx.shadowColor = this.color;
        ctx.fillStyle   = 'rgba(0, 0, 0, 1)';
        ctx.globalCompositeOperation = 'lighter';
        ctx.beginPath();
        ctx.arc(this.x, this.y, this._currentRadius, 0, Math.PI * 2, false);
        ctx.fill();
        ctx.restore();
    }
});


/**
 * Lightning
 */
function Lightning(startPoint, endPoint, step) {
    this.startPoint = startPoint || new Vector();
    this.endPoint   = endPoint || new Vector();
    this.step       = step || 45;

    this.children = [];
}

Lightning.prototype = {
    color:         'rgba(255, 255, 255, 1)',
    speed:         0.025,
    amplitude:     1,
    lineWidth:     5,
    blur :         50,
    blurColor:     'rgba(255, 255, 255, 0.5)',
    points:        null,
    off:           0,
    _simplexNoise: new SimplexNoise(),
    // Case by child
    parent:        null,
    startStep:     0,
    endStep:       0,

    length: function() {
        return this.startPoint.distanceTo(this.endPoint);
    },

    getChildNum: function() {
        return children.length;
    },

    setChildNum: function(num) {
        var children = this.children, child,
            i, len;

        len = this.children.length;

        if (len > num) {
            for (i = num; i < len; i++) {
                children[i].dispose();
            }
            children.splice(num, len - num);

        } else {
            for (i = len; i < num; i++) {
                child = new Lightning();
                child._setAsChild(this);
                children.push(child);
            }
        }
    },

    update: function() {
        var startPoint = this.startPoint,
            endPoint   = this.endPoint,
            length, normal, radian, sinv, cosv,
            points, off, waveWidth, n, av, ax, ay, bv, bx, by, m, x, y,
            children, child,
            i, len;

        if (this.parent) {
            if (this.endStep > this.parent.step) {
                this._updateStepsByParent();
            }

            startPoint.set(this.parent.points[this.startStep]);
            endPoint.set(this.parent.points[this.endStep]);
        }

        length = this.length();
        normal = Vector.sub(endPoint, startPoint).normalize().scale(length / this.step);
        radian = normal.angle();
        sinv   = Math.sin(radian);
        cosv   = Math.cos(radian);

        points    = this.points = [];
        off       = this.off += random(this.speed, this.speed * 0.2);
        waveWidth = (this.parent ? length * 1.5 : length) * this.amplitude;
        if (waveWidth > 750) waveWidth = 750;

        for (i = 0, len = this.step + 1; i < len; i++) {
            n = i / 60;
            av = waveWidth * this._noise(n - off, 0) * 0.5;
            ax = sinv * av;
            ay = cosv * av;

            bv = waveWidth * this._noise(n + off, 0) * 0.5;
            bx = sinv * bv;
            by = cosv * bv;

            m = Math.sin((Math.PI * (i / (len - 1))));

            x = startPoint.x + normal.x * i + (ax - bx) * m;
            y = startPoint.y + normal.y * i - (ay - by) * m;

            points.push(new Vector(x, y));
        }

        children = this.children;

        for (i = 0, len = children.length; i < len; i++) {
            child = children[i];
            child.color     = this.color;
            child.speed     = this.speed * 1.35;
            child.amplitude = this.amplitude;
            child.lineWidth = this.lineWidth * 0.75;
            child.blur      = this.blur;
            child.blurColor = this.blurColor;
            children[i].update();
        }
    },

    draw: function(ctx) {
        var points = this.points,
            children = this.children,
            i, len, p, d;

        // Blur
        if (this.blur) {
            ctx.save();
            ctx.globalCompositeOperation = 'lighter';
            ctx.fillStyle   = 'rgba(0, 0, 0, 1)';
            ctx.shadowBlur  = this.blur;
            ctx.shadowColor = this.blurColor;
            ctx.beginPath();
            for (i = 0, len = points.length; i < len; i++) {
                p = points[i];
                d = len > 1 ? p.distanceTo(points[i === len - 1 ? i - 1 : i + 1]) : 0;
                ctx.moveTo(p.x + d, p.y);
                ctx.arc(p.x, p.y, d, 0, Math.PI * 2, false);
            }
            ctx.fill();
            ctx.restore();
        }

        ctx.save();
        ctx.lineWidth = random(this.lineWidth, 0.5);
        ctx.strokeStyle = this.color;
        ctx.beginPath();
        for (i = 0, len = points.length; i < len; i++) {
            p = points[i];
            ctx[i === 0 ? 'moveTo' : 'lineTo'](p.x, p.y);
        }
        ctx.stroke();
        ctx.restore();

        // Draw children
        for (i = 0, len = this.children.length; i < len; i++) {
            children[i].draw(ctx);
        }
    },

    dispose: function() {
        if (this._timeoutId) {
            clearTimeout(this._timeoutId);
        }
        this._simplexNoise = null;
    },

    _noise: function(v) {
        var octaves = 6,
            fallout = 0.5,
            amp = 1, f = 1, sum = 0,
            i;

        for (i = 0; i < octaves; ++i) {
            amp *= fallout;
            sum += amp * (this._simplexNoise.noise2D(v * f, 0) + 1) * 0.5;
            f *= 2;
        }

        return sum;
    },

    _setAsChild: function(lightning) {
        if (!(lightning instanceof Lightning)) return;
        this.parent = lightning;

        var self = this,
            setTimer = function() {
                self._updateStepsByParent();
                self._timeoutId = setTimeout(setTimer, randint(1500));
            };

        self._timeoutId = setTimeout(setTimer, randint(1500));
    },

    _updateStepsByParent: function() {
        if (!this.parent) return;
        var parentStep = this.parent.step;
        this.startStep = randint(parentStep - 2);
        this.endStep   = this.startStep + randint(parentStep - this.startStep - 2) + 2;
        this.step = this.endStep - this.startStep;
    }
};


/**
 * Rect
 */
function Rect(x, y, width, height) {
    this.x = x || 0;
    this.y = y || 0;
    this.width  = width || 0;
    this.height = height || 0;
    this.right  = this.x + this.width;
    this.bottom = this.y + this.height;
}


// Helpers

function random(max, min) {
    if (typeof max !== 'number') {
        return Math.random();
    } else if (typeof min !== 'number') {
        min = 0;
    }
    return Math.random() * (max - min) + min;
}


function randint(max, min) {
    if (!max) return 0;
    return random(max + 1, min) | 0;
}



// Initialize

(function() {

    // Vars

    var canvas, context,
        centerX, centerY, grad,
        mouse,
        bounds,
        points,
        lightning,
        gui, control;


    // Event Listeners

    function resize() {
        canvas.width  = window.innerWidth;
        canvas.height = window.innerHeight;
        centerX = canvas.width * 0.5;
        centerY = canvas.height * 0.5;
        context = canvas.getContext('2d');
        grad = context.createRadialGradient(centerX, centerY, 0, centerX, centerY, Math.sqrt(centerX * centerX + centerY * centerY));
        grad.addColorStop(0, 'rgba(0, 0, 0, 0)');
        grad.addColorStop(1, 'rgba(0, 0, 0, 0.4)');
    }

    function mouseMove(e) {
        mouse.set(e.clientX, e.clientY);

        var i, hit = false;
        for (i = 0; i < 2; i++) {
            if ((!hit && points[i].hitTest(mouse)) || points[i].dragging)
                hit = true;
        }
        document.body.style.cursor = hit ? 'pointer' : 'default';
    }

    function mouseDown(e) {
        for (var i = 0; i < 2; i++) {
            if (points[i].hitTest(mouse)) {
                points[i].startDrag();
                return;
            }
        }
    }

    function mouseUp(e) {
        for (var i = 0; i < 2; i++) {
            if (points[i].dragging)
                points[i].endDrag();
        }
    }


    // GUI Control

    control = {
        childNum: 3,
        color: [255, 255, 255],
        backgroundColor: '#0b5693'
    };


    // Init

    canvas = document.getElementById('c');

    window.addEventListener('resize', resize, false);
    resize(null);

    bounds = new Rect(0, 0, canvas.width, canvas.height);
    mouse  = new Vector();

    lightning = new Lightning();

    points = [
        new Point(centerX - 200, centerY, lightning.lineWidth * 1.25),
        new Point(centerX + 200, centerY, lightning.lineWidth * 1.25)
    ];

    lightning.startPoint.set(points[0]);
    lightning.endPoint.set(points[1]);
    lightning.setChildNum(3);

    canvas.addEventListener('mousemove', mouseMove, false);
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);


    // GUI

    gui = new dat.GUI();
    gui.add(lightning, 'amplitude', 0, 2).name('Amplitude');
    gui.add(lightning, 'speed', 0, 0.1).name('Speed');
    gui.add(control, 'childNum', 0, 10).step(1).name('Child Num').onChange(function() {
        lightning.setChildNum(control.childNum | 0);
    });
    gui.addColor(control, 'color').name('Color').onChange(function() {
        var c = control.color;
        var r = (c[0] || 0) | 0, g = (c[1] || 0) | 0, b = (c[2] || 0) | 0,
            i, len;

        lightning.color     = 'rgb(' + r + ',' + g + ',' + b + ')';
        lightning.blurColor = 'rgba(' + r + ',' + g + ',' + b + ', 0.5)';
        for (i = 0, len = points.length; i < len; i++) {
            points[i].color = lightning.color;
        }
    });
    gui.add(lightning, 'lineWidth', 1, 10).name('Line Width').onChange(function() {
        for (var i = 0, len = points.length; i < len; i++) {
            points[i].radius = lightning.lineWidth * 1.25;
        }
    });
    gui.add(lightning, 'blur', 0, 100).name('Blur');
    gui.addColor(control, 'backgroundColor').name('Background');
    gui.close();


    // Start Update

    var loop = function() {
        context.save();
        context.fillStyle = control.backgroundColor;
        context.fillRect(0, 0, canvas.width, canvas.height);
        context.fillStyle = grad;
        context.fillRect(0, 0, canvas.width, canvas.height);
        context.restore();

        lightning.startPoint.set(points[0]);
        lightning.endPoint.set(points[1]);
        lightning.step = Math.ceil(lightning.length() / 10);
        if (lightning.step < 5) lightning.step = 5;

        lightning.update();
        lightning.draw(context);

        var i, p;

        for (i = 0; i < 2; i++) {
            p = points[i];
            if (p.dragging) p.drag(mouse);
            p.update(points, bounds);
            p.draw(context);
        }

        requestAnimationFrame(loop);
    };
    loop();

})();

This awesome code ( Lightning ) is write by Akimitsu Hamamuro, you can se more from this user in the personal repository

You can find the original code on Codepen.io

2018 © Akimitsu Hamamuro