Animation script that building random circles and lines in movement. You can control styles, objects sizes, and density. Animation adaptive. It was developed as a background decoration but its possible to use in any creative way. You can change attributes of the canvas tag to edit animation.

Now explaining code by blocks...

HTML

Animation positioning on the page with Canvas tag. Attributes of the tag (listed at the end of the article) reading in JavaScript and it is building animation according to the values.

  <canvas
        class="animated-block"
        height="400"
        data-dot-size="4"
        data-density="2"
        data-speed="1"
        data-frame-rate="50"
        data-dot-color="#90CAF9"
        data-line="true"
        data-line-color="#90CAF9"
        style="background: linear-gradient(45deg, #2196f3 0%,#1e88e5 100%)">
</canvas>

All JavaScript code packed in a single class. This class creating an object when attached to the canvas, in such a way we can use multiple animations on a single page.

Constructor

At the beginning of the constructor, we are reading canvas attributes and saving it to an object.

  this.dotSize = canvas.dataset.dotSize; // size of the dot
this.density = canvas.dataset.density; // density of objects
this.speed = canvas.dataset.speed; // objects max speed
this.frames = canvas.dataset.frameRate; // milliseconds per frame - frame rate
this.lines = canvas.dataset.line; // lines switcher
this.fillColor = canvas.dataset.dotColor; // color of the dot
this.strokeColor = canvas.dataset.lineColor; // color of the line
this.opacity = 1;
this.opacityDirection = 0;
this.connectionsSwitch = false;

Next, we dealing with animation width. First, we receive screen width and applying resizing event subscription.

  canvas.width = window.innerWidth;
window.addEventListener('resize', function() {
    canvas.width = window.innerWidth;
});

Just getting a context of the canvas.

  this.ctx = canvas.getContext('2d');
this.ctx.fillStyle = this.fillColor;
this.ctx.strokeStyle = this.strokeColor;

Now calculating the density of objects. I am using density attribute and calculating direct amount of elements relatively to canvas size.

  this.objectsCount = (this.ctx.canvas.height * this.ctx.canvas.width) / 100000 * this.density;

Here I creating an array of objects using a random number generator to assign their position, speed and direction of movement.

  this.objects = [];
for (var i = 0; i < this.objectsCount; i++) {
        this.objects[i] = {};
        this.objects[i].position = {};
        this.objects[i].position.x = Math.floor((Math.random() * this.ctx.canvas.width) + 1);
        this.objects[i].position.y = Math.floor((Math.random() * this.ctx.canvas.height) + 1);
        this.objects[i].direction = {};
        this.objects[i].direction.x = Math.round(Math.random());
        this.objects[i].direction.y = Math.round(Math.random());
        this.objects[i].speed = {};
        this.objects[i].speed.x = Math.random() * this.speed;
        this.objects[i].speed.y = Math.random() * this.speed;
}

Drawing

This is a method that repeats himself after a specific amount of milliseconds to draw a frame. Basically it is a frame controller.

At first clearing old frame.

  this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

Now in the cycle we drawing each object position in the current frame.

  this.dot( this.objects[i].position.x, this.objects[i].position.y );
if (this.lines == 'true' && !!this.objects[(i+1)]){
    if ( (i % 2 == 0) && this.connectionsSwitch )
        this.line( this.objects[i].position.x, this.objects[i].position.y, this.objects[(i+1)].position.x, this.objects[(i+1)].position.y );
    else if ( (i % 2 != 0) && !this.connectionsSwitch )
        this.line( this.objects[i].position.x, this.objects[i].position.y, this.objects[(i+1)].position.x, this.objects[(i+1)].position.y );
}

After that we using speed and direction values to calculate the position of the objects in the next frame. This will draw when drawing method will be called next time. Also, we cant change direction if elements will reach canvas borders.

  // horizontal
if (this.objects[i].direction.x) {
    var coord = this.objects[i].position.x + this.objects[i].speed.x;
    if ( coord > this.ctx.canvas.width) {
        coord = this.ctx.canvas.width;
        this.objects[i].direction.x = 0;
    }
    this.objects[i].position.x = coord;
} else {
    var coord = this.objects[i].position.x - this.objects[i].speed.x;
    if ( coord < 0) {
        coord = 0;
        this.objects[i].direction.x = 1;
    }
    this.objects[i].position.x = coord;
}
// vertical
if (this.objects[i].direction.y) {
    var coord = this.objects[i].position.y + this.objects[i].speed.y;
    if ( coord > this.ctx.canvas.height) {
        coord = this.ctx.canvas.height;
        this.objects[i].direction.y = 0;
    }
    this.objects[i].position.y = coord;
} else {
    var coord = this.objects[i].position.y - this.objects[i].speed.y;
    if ( coord < 0) {
        coord = 0;
        this.objects[i].direction.y = 1;
    }
    this.objects[i].position.y = coord;
}

Now we doing the same with opacity animation setting.

  if (this.opacity < 0.02){
    this.opacityDirection = 1;
    if(this.connectionsSwitch) this.connectionsSwitch = false;
    else this.connectionsSwitch = true;
}else if (this.opacity > 0.98) this.opacityDirection = 0;
if (this.opacityDirection) this.opacity = this.opacity + 0.01;
else this.opacity = this.opacity - 0.01;
this.ctx.strokeStyle = this.hexToRgb( this.strokeColor, this.opacity );

In the end, we calling this method again after the configured amount of time.

  var obj = this;
if (obj.frames != 0) {
    setTimeout(function () {
        window.requestAnimationFrame(obj.draw.bind(obj));
    }, obj.frames);
}

This was the main method, but there are a couple additional methods that drawing using.

Additional Methods

There is a drawing of the dots and the lines methods. They are simple.

  // drawing dot
dot(x,y) {
    this.ctx.fillStyle = this.fillColor;
    this.ctx.beginPath();
    this.ctx.arc(x, y, this.dotSize, 0, Math.PI * 2, true);
    this.ctx.fill();
}

// drawing line line(fx,fy,tx,ty) { this.ctx.strokeStyle = this.strokeColor; this.ctx.beginPath(); this.ctx.moveTo(fx,fy); this.ctx.lineTo(tx, ty); this.ctx.stroke(); }

The last one is a converter of the colors formats. In attributes of canvas, you can assign a color in HEX and RGBA types. I was needed this to convert colors to the same type, to work with it in the JavaScript.

  hexToRgb(hex, alpha) {
    hex   = hex.replace('#', '');
    var r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
    var g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
    var b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
    if ( alpha ) {
        return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')';
    } else {
        return 'rgb(' + r + ', ' + g + ', ' + b + ')';
    }
 }

Subscription

Now, all we need is to create an individual object for each animation block on the page. For this we selecting all canvas tags, attaching animation objects to it and calling first frame draw.

  window.onload = function() {
    var animatedBlocks = [];
    Array.prototype.forEach.call(document.getElementsByClassName('animated-block'), function(el, i) {
        animatedBlocks[i] = new canvasClasss(el);
        window.requestAnimationFrame( animatedBlocks[i].draw.bind(animatedBlocks[i]) );
    });
}

List of Attributes

  • height - height of the block in pixels;
  • data-dot-size - the size of the dot in pixels. 0 - turned off dot;
  • data-density - an amount of the objects. You can set an integer o float number;
  • data-speed- maximum speed of the objects. You can set an integer o float number. 0 - objects do not move;
  • data-frame-rate - countdown to next frame in milliseconds. Lower means more frames per second. Add more frames if you are adding speed. 0 - animation disabled;
  • data-dot-color - a color of the dots. You can set HEX and RGBA values, for example: #e4efe9, #e4e, rgba(100%, 100%, 100%, 0.5);
  • data-line - lines display boolean switcher;
  • data-line-color - a color of the lines. You can set HEX values;
  • style - you can use this attribute to add any CSS styles.

Contacts

Please feel free to contact me :)


53 0 1