Flicker effect with jQuery

During the design process of a recent project homepage, I wanted to use an effect that native jQuery plugins or javascript effects could not achieve in the way I wanted them to. My idea was to have as spooky a theme as I could on the site and the main feature of the homepage would be a zombie girl lurking in the woods :)

Once I had the design down in photoshop, I was trying to figure out a way of making the girl stand out when it came to putting the design in a browser, just in case the user had missed her and the eerie effect proved useless. I love horror films and those spine tingling moments in films when something unsettles you. A particular scene in the film ‘The Ring’ inspired me to use a flickering effect on the girl to give the whole scene an unsettling appearance.

The first thing was to seperate the girl from the rest of the image using css, so that I could target her with jQuery more effectively.

<div id="topnav">
<ul>
    <li class="current_page_item"><a href="/"><span>run</span> home</a></li>
    <li><a href="/web-design-bournemouth">what <span>am i</span></a></li>
    <li><a href="/why-am-i">why <span>am i</span></a></li>
    <li><a href="/summon-me">summon <span>me</span></a></li>
</ul>
</div>
<script type="text/javascript">// <![CDATA[
  if(!$.browser.msie){$('#main .right .zombie').css({opacity:0});}
// ]]></script>

I did this by structuring the page and putting the zombie div after the topnav div. I also added a small piece of jquery just after the zombie div to hide it from view immediately. This is to make sure that everything is set up correctly before the sequence begins. The following shows the css rules applied to the zombie div.

As ever, IE shows problems when trying to animate opacity values and for now I decided not to make this effect available to IE browsers

#main .right .zombie {
background:transparent url(../images/zombie.png) no-repeat scroll 180px 185px;
height:370px;
position:relative;
}

Knowing that all I want to do for now is flicker the div, I was safe to add position and structure using css to move the zombie image where I wanted it.

As with any new idea, planning and setting things up with your goal in mind is essential. Most of the donkey work is done in setting things up correctly in the first place. I almost knew what the main jQuery needed to do once I’d reached this point in the development process. It mostly consists of stringed animations and pauses but timing them was the tricky part. Flickers needed to seem almost random, so I mixed long pauses in with quick changes in opacity till it looked right.

$zombie = $('#main .right .zombie');
if(!$.browser.msie){
$zombie.animate({opacity:0}, {duration:1})
.animate({ opacity: 0 },6000)
.animate({opacity:0}, {duration:1})
.animate({opacity:0}, {duration:100})
.animate({opacity:0.5}, {duration:10})
.animate({opacity:0}, {duration:300})
.animate({opacity:0.6}, {duration:100})
.animate({opacity:0}, {duration:200})
.animate({opacity:1}, {duration:100})
.animate({opacity:0}, {duration:100})
.animate({opacity:0.3}, {duration:100})
.animate({opacity:1}, {duration:10})
.animate({opacity:1}, {duration:10000});
function runit(){
$zombie
.animate({opacity:1}, {duration:200})
.animate({opacity:0}, {duration:100})
.animate({opacity:1}, {duration:10})
.animate({opacity:0}, {duration:10})
.animate({opacity:1}, {duration:10})
.animate({opacity:0}, {duration:50})
.animate({opacity:1}, {duration:100})
.animate({ opacity: 1 },20000, function(){runit();});
}
runit();
}

Another hurdle that needed jumping was the looping issue. I wanted the effect to be continuous. I got over this one by effectively having a function within a function. runit() has an animation sequence within it. This function is called after an initial animation sequence. The clever bit is that the function gets called at the end of itself, this keeps the flicker going forever.

Yet another thing that needed resolving was the fact that Different things load at different times. With everything else loading around it, the zombie girl animation was in danger of simply being lost because the user would be distracted by other elements popping up around it. I needed the girl to be the focus of the users attention for it to be effective. I utilised jQueries excellent bind feature to execute the above only after everything within the DOM window had loaded. I wrapped the animation sequence in this bind function and things worked brilliantly.

$(window).bind('load', function() {
$zombie = $('#main .right .zombie');
if(!$.browser.msie){
$zombie.animate({opacity:0}, {duration:1})
.animate({ opacity: 0 },6000)
.animate({opacity:0}, {duration:1})
.animate({opacity:0}, {duration:100})
.animate({opacity:0.5}, {duration:10})
.animate({opacity:0}, {duration:300})
.animate({opacity:0.6}, {duration:100})
.animate({opacity:0}, {duration:200})
.animate({opacity:1}, {duration:100})
.animate({opacity:0}, {duration:100})
.animate({opacity:0.3}, {duration:100})
.animate({opacity:1}, {duration:10})
.animate({opacity:1}, {duration:10000});
function runit(){
$zombie
.animate({opacity:1}, {duration:200})
.animate({opacity:0}, {duration:100})
.animate({opacity:1}, {duration:10})
.animate({opacity:0}, {duration:10})
.animate({opacity:1}, {duration:10})
.animate({opacity:0}, {duration:50})
.animate({opacity:1}, {duration:100})
.animate({ opacity: 1 },20000, function(){runit();});
}
runit();
}
}});

Webegg © 2012


Thank you