4
\$\begingroup\$

I need a hoverable transparent animation for a website, so that it glows when the mouse is over it. I could use two gifs or svgs one on top of another, but (as far as I know) there's no control of the current frame so I tried spritesheets with JavaScript and an if/else inside of every image in order to show the hovered, glowing version or the non-glowing depending on the users's mouse position.

However, there is yet another thing I tried: instead of a single spritesheet, why not cut it and put it all in the same position within a container div? They all start in display:none and they appear at the rate JavaScript tells them to. It works quite nicely. Here is my HTML:

    <div id="animation">
        <img src="frame1.png">
        <img src="frame1glow.png">
        <img src="frame2.png">
        <img src="frame2glow.png">
    </div>

There are many more frames, of course. This is the JavaScript controller (for two frames):

var animation_hovered = false;

animation.onmouseover = function(){animation_hovered = true;}
animation.onmouseout = function(){animation_hovered = false;}

window.setInterval(function(){
  if(animation_hovered == false){
  document.querySelector('#animation img:nth-child(1)').style.display = "initial";
  document.querySelector('#animation img:nth-child(4)').style.display = "none";
  document.querySelector('#animation img:nth-child(3)').style.display = "none";
  }
else{
  document.querySelector('#animation img:nth-child(2)').style.display = "initial";
  document.querySelector('#animation img:nth-child(4)').style.display = "none";
  document.querySelector('#animation img:nth-child(3)').style.display = "none";
  }
window.setTimeout(function(){
  if(animation_hovered == false){
    document.querySelector('#animation img:nth-child(3)').style.display = "initial";
    document.querySelector('#animation img:nth-child(1)').style.display = "none";
    document.querySelector('#animation img:nth-child(2)').style.display = "none";
    }
  else{
    document.querySelector('#animation img:nth-child(4)').style.display = "initial";
    document.querySelector('#animation img:nth-child(1)').style.display = "none";
    document.querySelector('#animation img:nth-child(2)').style.display = "none";        
   }
  }, 300);
}, 600);

It seems bulky, but this approach gives you absolute control over your frames and it works nicely. Also, by not using a spritesheet, you can keep your layout pretty simple (or at least a big spritesheet seems to me a bit difficult to hide in my web interface; cut it seems simpler).

Does anyone think I am doing something wrong or could be enhanced in any way?

\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review, I hope you get some great answers! \$\endgroup\$ – Phrancis Mar 23 '15 at 20:45
2
\$\begingroup\$

First of all, this kind of manipulation is done using CSS. E.g. http://blog.teamtreehouse.com/css-sprite-sheet-animations-steps

Nevertheless, let's see what can be improved:

Instead of nth-child selectors, use classes instead

It provides some meaning to the images, and you can replace the src easily afterwards:

<div id='animation'>
    <img class='first-frame' src='...'>
    <img class='first-frame-glow' src='...'>
    <img class='second-frame' src='...'>
    <img class='second-frame-glow' src='...'>     
</div>

Refactor the code into a general function that handles the styling

var style_switcher = function(first, second, third) {
    document.querySelector(first).style.display = "initial";
    document.querySelector(second).style.display = "none";
    document.querySelector(third).style.display = "none";
};

Use named constants

var TIMEOUT = 300;
var INTERVAL = 600;

This will make things easier when you want to change the values.

Put everything together

window.setInterval(function(){
    if(animation_hovered == false){
        style_switcher('.first-frame', '.second-frame-glow', '.second-frame');
    }else{
        style_switcher('.first-frame-glow', '.second-frame-glow', '.second-frame');
    }
    window.setTimeout(function(){
        if(animation_hovered == false){
            style_switcher('.second-frame', '.first-frame', '.first-frame-glow');
        }else{
            style_switcher('.second-frame-glow', '.first-frame', '.first-frame-glow');
        }
    }, TIMEOUT);
}, INTERVAL);

If there is more common behavior, you can abstract that into a function.

Good luck!

\$\endgroup\$
  • 1
    \$\begingroup\$ To add more context to your post, instead of just saying what you should do, say why you should do it. \$\endgroup\$ – SirPython Mar 23 '15 at 22:13
  • \$\begingroup\$ Actually I can do it with pure CSS, I just realized. Anyway, I learned a lot. Thank you all! \$\endgroup\$ – Tomás Perales Monroy Mar 30 '15 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.