JavaScript object for an animated appearance of elements. You can control speed, positions, and appearance of elements of this animation. Animation adaptive. It was developed as a part of a landing page. You can change animation array to edit animation.

Now explaining code by blocks...

Animation Object

The animation consists of two big parts, animation initialization logic and drawing logic. All drawing functionality is contained inside the constructor function because old platform support was required in a project. By packing drawing logic in one place we can use multiple animations on a single page. The animation built by JavaScript array of description (listed at the initialization section of the article) and time starter hooks.

In the beginning, we saving context data to the animation object.

  this.animation = animation;
this.frames = 10; // animation speed is relative to this variable
this.ctx = canvas.getContext('2d');

Then we need to load all the images. For this, we creating a list of files and checking download status of each element. After, all components are loaded we requesting the first frame.

  this.files = {};
this.files.counter = 0;
this.files.downloads = [];
for (var i=0; i < this.animation.length; i++) {
  if (this.animation[i].type == 'image') {
    this.files.counter++;
    var img = new Image();
    img.src = this.animation[i].link;
    var obj = this;
    img.onload = function() {
      obj.files.downloads.push(true);
      if(obj.files.downloads.length == obj.files.counter){
        window.requestAnimationFrame(obj.draw.bind(obj));
      }
    }
    this.animation[i].image = img;
    this.animation[i].opacity = 0;
  }
  this.animation[i].frame = 0;
}
if (!this.files.counter) window.requestAnimationFrame(this.draw.bind(this));

Now we calculating positions of all elements. Positions calculating only if start trigger is enabled. For each type of animation, we calculating future element position. Defining next position of the lines dots have complicated formula because it masts work with all four directions.

  this.positions = function() {
    for (var i=0; i < this.animation.length; i++) {
        var obj = this.animation[i];
        if(obj.start){

            if (obj.type == 'image') {
                obj.precent = [];
                obj.precent.pos = [];

                // object location
                obj.precent.pos[0] = this.precent(obj.pos[0],true);
                obj.precent.pos[1] = this.precent(obj.pos[1],false);
                obj.precent.width = obj.precent.height = this.precent(obj.width,true);

                // object animation
                obj.opacity = obj.opacity + obj.speed;

            } else if (obj.type == 'line') {
                obj.precent = [];
                obj.precent.to = [];
                obj.precent.from = [];
                obj.precent.mid = [];

                // object location
                obj.precent.to[0] = this.precent(obj.to[0],true);
                obj.precent.to[1] = this.precent(obj.to[1],false);
                obj.precent.from[0] = this.precent(obj.from[0],true);
                obj.precent.from[1] = this.precent(obj.from[1],false);

                // object animation
                if (obj.to[0]>obj.from[0]) {
                    var move = (obj.from[0]-obj.to[0])/100 * obj.speed * obj.frame;
                    var newPos = this.precent( (obj.from[0]-move) ,true);
                    if (newPos<=obj.precent.to[0]) obj.precent.mid[0] = newPos;
                    else obj.precent.mid[0] = obj.precent.to[0];
                } else if (obj.to[0]=obj.precent.to[0]) obj.precent.mid[0] = newPos;
                    else obj.precent.mid[0] = obj.precent.to[0];
                } else obj.precent.mid[0] = obj.precent.to[0];
                if (obj.to[1]>obj.from[1]) {
                    var move = (obj.to[1]-obj.from[1])/100 * obj.speed * obj.frame;
                    var newPos = this.precent( (obj.from[1]+move) ,false);
                    if (newPos<=obj.precent.to[1]) obj.precent.mid[1] = newPos;
                    else obj.precent.mid[1] = obj.precent.to[1];
                } else if (obj.to[1]=obj.precent.to[1]) obj.precent.mid[1] = newPos;
                    else obj.precent.mid[1] = obj.precent.to[1];
                } else obj.precent.mid[1] = obj.precent.to[1];
                obj.frame++;
                
            }
        }
    }
}

Next comes drawing method. Basically this is an events controllers, it is using all other methods to build each frame. At first cleaning previous frame. Then calling counter of the next frame elements and drawing them. After that calling the next frame - this function calls its self recursively.

  this.draw = function() {
    // cleaning frame
    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

    // drawing
    this.positions();
    for (var i=0; i < this.animation.length; i++) {
        if (this.animation[i].type == 'line') this.line(this.animation[i]);
        else if (this.animation[i].type == 'image') this.image(this.animation[i]);
    }

    // frame recursions
    var obj = this;
    setTimeout(function () {
        window.requestAnimationFrame(obj.draw.bind(obj));
    }, obj.frames);
}

Also, there is a drawing of the images and the lines methods. They are simple.

And in the end, we have percentage converter. All sizes are relative for the purposes of adaptation. Locations are set in percentages and here converting into pixels.

  this.precent = function(precent,orientation) {
    if (orientation) return (this.ctx.canvas.width/100)*precent;
    else return (this.ctx.canvas.height/100)*precent;
}

Initialization

All animation behavior is described in formatted JavaScript array of values. This array is given as a configuration setup when the animation object created. This is the list of values with explanations:

type - 'image' or 'line' describes animation type;

link - link to an image file of the image animation;

pos - position of the image, in %, from the top left corner;

width - the size of the image in % or size of the line in px;

speed - the speed of the element appearance;

start - animation starts if that trigger set to 'true';

from - start position, in %, of the line animation;

to - end position, in %, of the line animation;

color - a color of the line;

  var animation = [
    {
        'type':'image',
        'link':'http://elements.codepen.envato-developing.xyz/KrKyro/1.svg',
        'pos':[5,35],
        'width':10,
        'speed': 0.05,
        'start': false
    },
    {
        'type':'line',
        'from': [15,0],
        'to':[35,100],
        'color':'#7cab8d',
        'width':3,
        'speed': 2,
        'start': false
    }
];

// object creation
var canvasObj = new canvasConstructor( document.getElementById('animation'), animation);

Next, we need to set up a start hook in case if it was not activated in the description array. In my case, I just activate every element with a 500 millisecond delay.

  animation.forEach(function(element, index) {
    setTimeout(function(){ canvasObj.animation[index].start = true; }, index * 500);
});

Last but not least. To activate adaptation a setting up resize handler function.

  function canvasResize(){
    document.getElementById('animation').setAttribute("width", window.innerWidth);
    document.getElementById('animation').setAttribute("height", window.innerHeight);
}
canvasResize();
window.addEventListener("resize", canvasResize);

Contacts

Please feel free to contact me :)


32 0 1