div#params
  label(for="#num_of_dots") Number of dots:
  input(type="number" value="80" onChange="setParams()")#num_of_dots

  label(for="#max_distance") Maximum distance:
  input(type="number" value="150" onChange="setParams()")#max_distance

div#blur
  
div#container
  h1 Floating Dots with Pixi.js
  p Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
  
View Compiled
html
  overflow hidden
  background #042C52
  background-image radial-gradient(circle farthest-corner at 50% 0%, #1464B2, #042C52)
  
label, h1, p
  color #e0e0e0

p
  width 40em
  
label
  display block
  opacity .75
  margin-top 1em

#params
  top 20px
  left 20px
  position absolute
  opacity .9
  
#blur
  position absolute
  top 50%
  left 50%
  width 600px
  height 300px
  transform translateX(-50%) translateY(-50%)
  background rgba(#0E5191, 0.8)
  filter blur(40px)

#container
  position absolute
  top 50%
  left 50%
  transform translateX(-50%) translateY(-50%) 
View Compiled
(function(window, document, undefined) {
  var WIDTH = window.innerWidth;
  var HEIGHT = window.innerHeight;
  var body = document.getElementsByTagName('body')[0];

  var Dots = new Array();
  var TOTAL_DOTS = document.getElementById('num_of_dots').value;
  var DISTANCE = document.getElementById('max_distance').value;
  var GRAVITY = 0.0001;

  window.setParams = function() {
    TOTAL_DOTS = document.getElementById('num_of_dots').value;
    DISTANCE = document.getElementById('max_distance').value;

    if (TOTAL_DOTS < Dots.length) {
      var del = Dots.length - TOTAL_DOTS;
      Dots.splice(TOTAL_DOTS, del);
    }
    if (TOTAL_DOTS > Dots.length) {
      var create = TOTAL_DOTS - Dots.length;
      for (var i = 0; i < create; i++) {
        var dot = new Dot();
        Dots.push(dot);
      }
    }
  }

  function Dot() {
    this.x = 0;
    this.y = 0;
    this.vy = 0;
    this.vx = 0;
    this.r = 2 + 2 * Math.random();
    this.c = 0x86A4C1;

    this.reset();

  }

  Dot.prototype.reset = function() {
    this.x = (Math.random() * WIDTH);
    this.y = (Math.random() * HEIGHT);

    var rand = Math.random();
    this.vx = (2 * Math.random() + 0.1) * 3 / this.r;
    if (rand > .5) {
      this.vx = -1 * this.vx;
    }

    rand = Math.random();
    this.vy = (2 * Math.random() + 0.1) * 3 / this.r;
    if (rand > .5) {
      this.vy = -1 * (2 * Math.random() + 0.1) * 1;
    }
  }

  Dot.prototype.collisionCheck = function() {
    if (this.x < 0 - this.r - DISTANCE) this.x = WIDTH;
    if (this.x > WIDTH + this.r + DISTANCE) this.x = 0;
    if (this.y < 0 - this.r - DISTANCE) this.y = HEIGHT;
    if (this.y > HEIGHT + this.r + DISTANCE) this.y = 0;
  }

  for (var i = 0; i < TOTAL_DOTS; i++) {
    var dot = new Dot();
    Dots.push(dot);
  }

  function distance(x1, y1, x2, y2) {
    var xdiff = x1 - x2;
    var ydiff = y1 - y2;
    return Math.sqrt(xdiff * xdiff + ydiff * ydiff);
  }

  // create a renderer instance.
  var renderer = PIXI.autoDetectRenderer(WIDTH, HEIGHT, {
    'transparent':true,
    'autoResize': true,
    'antialias': true,
  });

  // add the renderer view element to the DOM
  document.body.appendChild(renderer.view);

  requestAnimationFrame(animate);
  
  var graphics = new PIXI.Graphics();
  
  function animate() {
    graphics.clear();  
    
    for (var i = 0; i < Dots.length; i++) {
      var dot1 = Dots[i];
      dot1.collisionCheck();
      drawDot(graphics, dot1);

      for (var j = i + 1; j < Dots.length; j++) {
        var dot2 = Dots[j];

        var x1 = dot1.x;
        var x2 = dot2.x;
        var y1 = dot1.y;
        var y2 = dot2.y;

        var dist = distance(x1, y1, x2, y2);
        if (dist <= DISTANCE) {
          var normalizedDist = dist / DISTANCE;
          
          var lineWidth = (dot1.r + dot2.r) * 0.3 / (2 * Math.sqrt(normalizedDist) + 0.00001);
          var alpha = 1.0 - (normalizedDist * normalizedDist);

          graphics.lineStyle(lineWidth, dot.c, alpha);
          
          var x1r = (0.5 + x1) << 0;
          var y1r = (0.5 + y1) << 0;
          var x2r = (0.5 + x2) << 0;
          var y2r = (0.5 + y2) << 0;
          
          graphics.moveTo(x1r, y1r);
          graphics.lineTo(x2r, y2r);
          
          var x1next = dot1.x + dot1.vx;
          var y1next = dot1.y + dot1.vy;
          var x2next = dot2.x + dot2.vx;
          var y2next = dot2.y + dot2.vy;
          var distnext = distance(x1next, y1next, x2next, y2next);
          if (distnext <= dist) {
            // dots are getting closer
            dot1.x += GRAVITY * dot2.r * x2 * Math.pow(normalizedDist, 2);
            dot2.x += GRAVITY * dot1.r * x1 * Math.pow(normalizedDist, 2);
            dot1.y += GRAVITY * dot2.r * y2 * Math.pow(normalizedDist, 2);
            dot2.y += GRAVITY * dot1.r * y1 * Math.pow(normalizedDist, 2);
          } else {
            dot1.x -= GRAVITY * dot2.r * x2 * Math.pow(normalizedDist, 2);
            dot2.x -= GRAVITY * dot1.r * x1 * Math.pow(normalizedDist, 2);
            dot1.y -= GRAVITY * dot2.r * y2 * Math.pow(normalizedDist, 2);
            dot2.y -= GRAVITY * dot1.r * y1 * Math.pow(normalizedDist, 2);
          }

        }
      }

      dot1.y += dot1.vy;
      dot1.x += dot1.vx;
    }

    // render the stage   
    renderer.render(graphics);

    requestAnimationFrame(animate);
  }

  function drawDot(graphics, dot) {
    graphics.beginFill(dot.c, 1.0);
    graphics.drawCircle(dot.x, dot.y, dot.r);
    graphics.endFill();
  }
  
}(window, document));

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js