📜 ⬆️ ⬇️

Sprite animation with CSS, JS and Canvas

Hello. A couple of days ago, I accidentally stumbled upon the “Space Rangers 2: Dominators” disk deposits. I did not install it, because now there is not enough time to immerse myself in it. And I decided to see what is on the disk. I looked at “Fan Art” and there I saw a program for picking up ranger resources. So I decided to see what our dominators are made of. After clicking a bit, I found the files with animation in GAI format. Started to admire that animation. Wanted to save them in the "GIF", but not how did not let that program save the animation? You can either save the current frame or all files in a PNG. I decided to save all the frames, and there were 150 of them. All the pictures are there, and why not do the same animation with them.

Sprite


In order to please yourself with such an animation, I took CSS + JS to help. What should I do with the 150th image files? Their weight is not critical, although they weigh more than a megabyte in total. The main problems with their simultaneous loading and manipulation. Therefore, I decided to “glue” them into one. Load only one, and with the help of CSS + JS will only have to properly position it.
It remains to choose the method of "gluing". I'm a programmer, and we are all lazy :), so I immediately rejected the manual gluing in the graphic editor. First of all, I rushed, as usual, to PHP and the GD library. But it leaves much to be desired for working with translucent PNGs. Then I thought, what else can you “glue” the pictures? And he dwelt on the fact that now everyone knows about what is considered to be fashionable now - HTML5. He is responsible for working with graphics - Canvas, and I really like this "snack". That's why I decided to “glue” on the “canvas”.
And so I add this tag to HTML:

<canvas id="sprite"> </canvas> 

In JS I will specify a mask for the name of the picture, the first picture and the number of the last one (I didn’t have to rename the pictures, since they all go in order). It should look something like this:

 var first = '000'; //     var last = 49; //   var num = 0; // var maskFileName = ['2HULL_PEOPLE_P_A_', '.png'];//   var dir = 'ship'; //,     

')
Now you can specify the size of the sprite that should work, and get its context:

 var canvas = document.getElementById("sprite"); //   canvas.width = (last + 1) * 75; // ,     canvas.height = 75; var width = 0; //,      var context = canvas.getContext("2d"); //  


To facilitate the conversion from number to line (analog str_pad from PHP) wrote a function converter with a wild name - zerofikator ():

 function zerofikator(int, length) { //       var prefix = ''; for (var i = num.toString().length; i < length; i++) { prefix += '0'; } return prefix + num; } 


Next, to draw on the “canvas” with our pictures, i.e. sprite creation, such a simple function:

 function draw() { var img = document.createElement('img'); /*          - */ img.onload = function () { //       context.drawImage(img, width, 0); width += 75; //       ,      ,     if (zerofikator(num, first.length) != zerofikator(last, first.length)) { //      num++; //  draw(); //    } } img.src = dir + '/' + maskFileName[0] + zerofikator(num, first.length) + maskFileName[1]; //      } draw(); //   


After launching such a page, we will see a wide frame-by-frame image, which, if we save, we can call it a sprite. By the way, the saved sprite weighs 615 KB, and 150 pictures 1 189 KB, hmm, here's another plus :).

I decided to add the conversion directly to the file by clicking on the canvas (solves the save problem for some browsers):

 canvas.onclick = function () { window.location = context.canvas.toDataURL('image/png'); }; 


image

Demo

Animation


Well, now, you can proceed to the animation.
In HTML, add a couple of “divchik”, with which we will continue to work:

 <div id="gun"></div> <div id="ship"></div> 


Then I wrote a function that animates sprites, but decided to make the settings separately in order to be able to use it for several "animations" at once:

 var styles = {}; styles.cursor = 'pointer'; //      ,   styles.width = '75px'; //  styles.height = '75px'; var elementId = 'gun'; // id ,     var imgName = 'canvas.png'; //    


And then the function itself:

 function spriteAnimation(elementId, imgName, styles) { var img = document.createElement('img'); var offset = 0; img.onload = function () { //    var element = document.getElementById(elementId); element.style.cursor = styles.cursor; element.style.width = styles.width; element.style.height = styles.height; element.style.background = "url('" + imgName + "') " + offset + "px 50%"; //     var i = 0; element.onmouseover = function() { //     interval = setInterval(function() { //  if (offset < img.width) { //    i++; //      } else { i = 0; //     } offset = 75 * i; //   element.style.background = "url('" + imgName + "') " + offset + "px 50%"; //   } , 1000/24) //24    } element.onmouseout = function(){ //      clearInterval(interval) //  ( ) } } img.src = imgName; //    } 


Oh yeah, you still have to call this function:

 spriteAnimation(elementId, imgName, styles); spriteAnimation('ship', 'ship.png', styles); 


And, to look right, you can add a picture with the background and position it correctly:

 <img src="fon.png" /> <div class="conteiner"><div id="gun"></div></div> 


image

Demo

Sources

As they say - “Just for fun”. How do you spend your time on rainy autumn evenings?

Source: https://habr.com/ru/post/130193/


All Articles