Tentacles

by soulwire

HTML

<script src="https://raw.github.com/soulwire/sketch.js/master/js/sketch.js"></script>
<script src="http://dat-gui.googlecode.com/git/build/dat.gui.min.js"></script>
<script src="http://dat-gui.googlecode.com/git/build/dat.color.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Quantico:400' rel='stylesheet' type='text/css'>
<header class="info">
    <hgroup class="about">
        <h1>Kinetic Creature</h1>
        <h3>Click anywhere to control</h3>
    </hgroup>
</header>
<div id="container"></div>

CSS

html, body {

    background: #f2f2f2;
    background: -moz-radial-gradient(center, ellipse cover,  #ffffff 0%, #ffffff 26%, #f5f5f5 59%, #f5f5f5 77%, #cecece 100%);
    background: -webkit-gradient(radial, center center, 0, center center, 100%, color-stop(0%,#ffffff), color-stop(26%,#ffffff), color-stop(59%,#f5f5f5), color-stop(77%,#f5f5f5), color-stop(100%,#cecece));
    background: -webkit-radial-gradient(center, ellipse cover,  #ffffff 0%,#ffffff 26%,#f5f5f5 59%,#f5f5f5 77%,#cecece 100%);
    background: -o-radial-gradient(center, ellipse cover,  #ffffff 0%,#ffffff 26%,#f5f5f5 59%,#f5f5f5 77%,#cecece 100%);
    background: -ms-radial-gradient(center, ellipse cover,  #ffffff 0%,#ffffff 26%,#f5f5f5 59%,#f5f5f5 77%,#cecece 100%);
    background: radial-gradient(ellipse at center,  #ffffff 0%,#ffffff 26%,#f5f5f5 59%,#f5f5f5 77%,#cecece 100%);
    overflow: hidden;
    padding: 0;
    margin: 0;
    height: 100%;
}

body:before {

    background-image:...

JavaScript

var settings = {
    interactive: false,
    darkTheme: false,
    headRadius: 60,
    thickness: 18,
    tentacles: 40,
    friction: 0.02,
    gravity: 0.5,
    colour: { h:0, s:0, v:0.1 },
    length: 70,
    wind: -0.5
};

var utils = {

    curveThroughPoints: function( points, ctx ) {

        var i, n, a, b, x, y;
        
        for ( i = 1, n = points.length - 2; i < n; i++ ) {

            a = points[i];
            b = points[i + 1];
            
            x = ( a.x + b.x ) * 0.5;
            y = ( a.y + b.y ) * 0.5;

            ctx.quadraticCurveTo( a.x, a.y, x, y );
        }

        a = points[i];
        b = points[i + 1];
        
        ctx.quadraticCurveTo( a.x, a.y, b.x, b.y );
    }
};

var Node = function( x, y ) {
    
    this.x = this.ox = x || 0.0;
    this.y = this.oy = y || 0.0;

    this.vx = 0.0;
    this.vy = 0.0;
};

var Tentacle = function( options ) {

    this.length = options.length || 10;
    this.radius = options.radius || 10;
    this.spacing = options.spacing || 20;
    this.friction = options.friction || 0.8;
    this.shade = random( 0.85, 1.1 );

    this.nodes = [];
    this.outer = [];
    this.inner = [];

    for ( var i = 0; i < this.length; i++ ) {
        this.nodes.push( new Node() );
    }
};

Tentacle.prototype = {

    move: function( x, y ) {
        
        this.nodes[0].x = x;
        this.nodes[0].y = y;
    },

    update: function() {

        var i, n, s, c, dx, dy, da, px, py, node, prev = this.nodes[0];
        var radius = this.radius * settings.thickness;
        var step = radius / this.length;

        for ( i = 1; i < this.length; i++ ) {

            node = this.nodes[i];

            node.x += node.vx;
            node.y += node.vy;

            dx = prev.x - node.x;
            dy = prev.y - node.y;
            da = Math.atan2( dy, dx );

            px = node.x + cos( da ) * this.spacing * settings.length;
            py = node.y + sin( da ) * this.spacing * settings.length;

           ...