Today we will analyze how the Explode effect is implemented without using any additional libraries.
→ Demo page:
Explode.js')
What you need to do:
- Cut element into N * N cells
- Place in each cell a copy of the "exploding" element
- Move margin of each cell to margin
- Animate each cell in the right direction.
Cut the itemThis is the easiest part. It is given: a certain element (for example, a picture or a block with text) for blasting and the number of N * N cells. We write a cycle in which we will create N * N divs and place, and then move a clone of our element.
We declare the variables necessary for the work:
function Explode( elem, N ) { N = N || 3; var pos = elem.getBoundingClientRect(); var top = pos.top; var left = pos.left; var width = Math.round( elem.clientWidth / N ); var height = Math.round( elem.clientHeight / N );
Create cells:
for ( var i = 0; i < N; i++ ) { for ( var j = 0; j < N; j++ ) { var tile = document.createElement( "DIV" ); document.body.appendChild( tile );
Set the necessary styles for the cell (this code is already inside the loop):
tile.style.position = "fixed"; tile.style.width = width + "px"; tile.style.height = height + "px"; tile.style.top = (top + height * i) + "px"; tile.style.left = (left + width * j) + "px"; // , // tile.style.overflow = "hidden";
Now we insert into each cell a clone of the element:
var tileContent = elem.cloneNode( true ); tile.appendChild( tileContent );
Now we need to move the clone in each cell so that the totality of all the cells looked exactly the same as the whole picture (now in each cell just its upper left corner).
tileContent.style.marginTop = (-height * i - pos.top) + "px"; tileContent.style.marginLeft = (-width * j - pos.left) + "px";
Those. move up the cell height multiplied by the cell number vertically. Similarly, we shift to the left.
-pos.top and
-pos.left are needed in case the element is shifted relative to the edge of the window (and it is most likely shifted). If these values are not taken away, then in the cell there will be a void or the wrong piece of the element - since “native” indents are taken into account.
The first half of the task is completed - the picture is “cut” into cells, with each of which you can work separately (namely, animate in different directions), but at the same time, the picture looks unchanged for the user.
Now we need to determine in which direction to animate each of the cells. Those. the top left should fly up and to the left, the cell to the right of it - just up, etc., thereby creating an “explosion” effect. It would be necessary to write the auxiliary function
direction (i, j, N) , where i and j is the cell number (in the loop), and N is the number of cells vertically and horizontally.
Attempt # 1At first there was the idea to return a certain number (for example, 0 - up, 1 - up and right, etc. clockwise) and determine the direction from it. At first glance, this seemed convenient and intuitive, but in fact generated a bunch of repetitive code in the style:
function direction (i, j, N) { if ( i == 0 && j == 0 ) return 7; // if ( i == 0 && j < N - 1 ) return 0; // if ( i == 0 && j == N - 1 ) return 1; // // [...]
I'm even afraid to imagine how to animate it. Write if for every occasion? No, you need something else.
This method has two drawbacks:
- bulkiness
- not quite correct values. For example, when N = 5, the upper left cell is animated to the left and up, everything is correct, however, the next cell to its right will fly straight up, although I would like up and a little to the left (but not so much)
Attempt # 2Create a two-dimensional N * N array, fill it with zeros, assign the value 1 to the element (i, j), and “search” for it, recursively cutting off the array in one layer (ie, making a 4x4 array from a 5x5 array, and so on). The obvious advantage is that there are no heaps of if-s and bulky code. The minus is the same - not exactly the desired values.
Unfortunately, I did not save the old source code, but again there is no desire to write this enigma - so this time without source code examples.
Attempt # 3, successfulVectors This is a compact and convenient solution that also solves the problem with “not quite correct values”. We will find out how far the cell is from the center, and calculate a certain vector
(x, y) , and based on
x and
y , animate the cell in directions.
function direction( i, j, N) { return [ (N-1) / 2 - i, j - (N-1) / 2 ] };
How simple it all was ...
For greater clarity, what values are given to cells with
N = 7 :
The case remains for small: to animate each cell in a given direction. In the
loop body, we call the helper function animateStart for each cell:
animateStart( tile, left + width * j, top + height * i, direction( i, j, N ) )
where the first argument is the cell itself, the second and third are its initial coordinates, and the last is the vector (x, y), which is represented by an array of two numbers.
Now let's start writing the animateStart function.
function animateStart( elem, posX, posY, dir ) { var vY = dir[0]; // var vX = dir[1]; // var start = new Date().getTime(); // // toX toY - // , (3, -3), // 150 // var toY = posY - 50 * vY; var toX = posX + 50 * vX; setTimeout( animate, 10 ); // // [...]
Now we will write the animate function. This is the progress of the animation. It will run every 10 milliseconds, moving the cell slightly in directions. This is what creates the effect of smooth animation.
function animate () { // , - 0, - 1 var m = (new Date().getTime() - start) / 500; if (m > 1) m = 1; elem.style.top = (posY + (toY - posY) * m) + "px"; // elem.style.left = (posX + (toX - posX) * m) + "px"; // elem.style.opacity = 1 - m; // "", if (m < 1) setTimeout( animate, 10 ); // 1, }
The final touch: remove the original item.
elem.parentNode.removeChild( elem );
Plugin ready! The demo page is at the very beginning of the article, and the js source is
here .