September 28, 2013

Released first stable version of js-parallax

Today I committed a stable version of the already announced jQuery plugin for retro-style parallax scrolling at Google Code. The plugin brings a very easy to use API to include a multi-layer image scroller on your sites.

Usage Example

<html>
    <head>
        <title>PARALLAX SCROLLER</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="application/javascript"> </script>
        <script src="http://parallax-js.googlecode.com/svn/tags/3/js/jquery.parallax.min.js" type="application/javascript"> </script>
        
        <script type="application/javascript">
         
            $(function() {
                $(".scrollerNew").parallax();
        });
        </script>
        
    </head>
    <body>
        <div class="content">Content</div>
        <ul class="scrollerNew">
            <li data-img='img/background.jpg' data-width='549px' data-height='168px' data-xi='6' data-repeat="repeat"></li>
            <li data-img='img/layer1.png' data-width='549px' data-height='168px' data-xi='10' data-repeat="repeat"></li>
            <li data-img='img/layer2.png' data-width='549px' data-height='168px' data-yi='14' data-repeat="repeat"></li>
        </ul>        
    </body>
</html>

The plugin and more detailed description are available at https://code.google.com/p/parallax-js/. More examples will be added soon. Not worth to mention, that the gadget in this blogs header uses js-parallax.

September 19, 2013

Close the tags, but close them fucking correctly.

Or: Do not mix HTML with X(HT)ML

Yesterday, our team struggled over a broken layout on IE8, while it all works well on FF, IE9+, Chrome, and Safari.
Initially, we thought we could fix it easily adapting the CSS, e.g. replacing display:inline-block by floating elements. This did not work. So, we checked the HTML structure for some missing close tags...everything looked correct. We started to be dispaired, as our ideas faded, and our knowledge came up to an end. Luckily, I saw a small warning showing up in the developer console in Browser Mode IE10 (not IE8), which seemed quite strange to me, as I did not find any problem within the referenced code.

The complete message (in portuguese) is the following: HTML1523: Marca de fim com sobreposição. As marcas devem ser estruturadas como "<b><i></i></b>" em vez de "<b><i></b></i>". It complains allegedly overlapping tags within the following HTML:

<div class="login">
    <asp:Label runat="server" ID="lnkLogin">Login<span class="seta-baixo"/></asp:Label>
    <asp:LinkButton runat="server" ID="lnkLogout">Logout</asp:LinkButton>
</div>

Do you see any problem?

Syntactically, everything seems fine, or not? Well, there is a small detail. I remembered that once I had problems with inline closed script tags. That is, when a script tag is closed in XHTML/XML manner, the script is not loaded correctly and cannot be used. That is because syntax of two similar but not identical languages are mixed up. Just to remember:

HTML is not XHTML(nor XML)!

You will run into problems, when mixing up XML-Syntax in HTML. Some browsers can deal with it, but others not. The solution was really simple. We closed the span tag the correct HTML way. You could say "Use the correct doctype definition to avoid the problem", and you would be right. But it is more bulletproof to use the HTML style, as it is also valid for XML!
<div class="login">
    <asp:Label runat="server" ID="lnkLogin">Login<span class="seta-baixo"></span></asp:Label>
    <asp:LinkButton runat="server" ID="lnkLogout">Logout</asp:LinkButton>
</div>

With the correction the layout works on all browsers as expected, even on IE8.
So, before you get nuts, and spent valuable time, remember to correctly close tags in HTML style.

September 14, 2013

Announcement: jQuery Plugin for Retro-Style Parallax-Scrolling

Currently, I am playing around a little bit with a new code editor called Brackets, which seems pretty cool. Maybe I will write something about it in the near future. Here I like to talk about the mini-project I chose to get familar with Brackets. I am developing a tiny jQuery extension/plugin/whatever for simple parallax scrolling. "Wow!", you say now, "Isn't there a bunch of them already out there? Why are you reinventing the wheel?" Yeah, you're right. But I am thinking about the oldschool parallax scrolling used in the 80th and early 90th in games, like Turrican, Shadow of Beast, Mario Bros., etc. That hippie pippie new school parallax is trendy, ... and others have done it already. I simply developed that toy mainly for training purposes, and people who are interested in it. Here is a scratch, on how to use it.
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>PARALLAX SCROLLER</title>
        <meta name="description" content="Testbed for parallax scroller development.">        
        <link rel="stylesheet" href="css/parallax-demo.css">    
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="application/javascript"> </script>
        <script src="../trunk/js/jquery.parallax.min.js" type="text/javascript"> </script>
        <script type="application/javascript">
            
            function sinEaseFunc(elapsedSeconds, step){                                    
                    return Math.sin(elapsedSeconds/10)*step;
                }
                
            function cosEaseFunc(elapsedSeconds, step){                                    
                    return Math.cos(elapsedSeconds/10)*step;
                }
            
         
            $(function() {
                $(".scrollerNew").parallax([
                    { xf : sinEaseFunc , yf : cosEaseFunc }
                ]);
        });
        </script>
        
    </head>
    <body>
        <div class="content">Content</div>
        <ul class="scrollerNew" data-fps='25'>
            <li data-img='img/tex5.jpg' data-width='549px' data-height='168px' data-xi='150' data-yi='150' data-repeat="repeat"></li>
            <li data-img='img/tex3.png' data-width='549px' data-height='168px' data-xi='12' data-yi='4' data-repeat="repeat"></li>
            <li data-img='img/texttex.png' data-width='549px' data-height='168px' data-yi='-10' data-repeat="repeat-y"></li>
            <li data-img='img/aufgerissen.png' data-width='549px' data-height='168px' data-repeat="no-repeat"></li>
        </ul>        
    </body>
</html>
As you may imagine, there are some interesting features for this scroller. It is/has
  • Easy to use
  • Time based animation, with configurable "Frames per second"
  • Highly customizable
  • Even non-linear translation possible
Currently, it is in an unstable development phase. But it is already worth to announce its existance. If you are interested feel free to try it. It is available at code.goggle. I plan to pimp this blog with that scroller.

September 04, 2013

requestAnimationFrame is what you need for browser-based animations

Are you still using setInterval for animating things on your website?

Forget about it! This is what I discovered yesterday. I started to make a simple parallax scrolling and used setInterval initially. I was not much convinced with the result, because I encountered some flicker and minor slowdowns. So, I searched for hints for optimizing my experience and discovered there is some relatively new technique out there called requestAnimationFrame. Here is what I've done intially
function ParallaxScroller() {
    var that = this;    
    var layers = [];
            
    this.addLayer = function(layer){
        layers.push(layer);    
    }
    
    
    this.start(timeout){
        setInterval(render, timeout);
    }
    
    this.render=function(){        
        for(var i=0; i<layers.length; ++i){
            layers[i].update();
        }        
    }
};

var scroller = new ParallaxScroller();
scroller.addLayer( /* layer */ );
scroller.start(50);
And here is the same code using requestAnimationFrame
function ParallaxScroller() {
    var that = this;    
    var layers = [];
            
    this.addLayer = function(layer){
        layers.push(layer);    
    }
        
    this.render=function(){        
        for(var i=0; i<layers.length; ++i){
            layers[i].update();
        }                
        requestAnimationFrame(that.render); // # HERE!
    }
};

var scroller = new ParallaxScroller();
scroller.addLayer( /* layer */ );
scroller.render();
The thoughtful reader may have noticed, that there is no interval passed to requestAnimationFrame. To understand what is happening here, it is vital to know about the essential difference between requestAnimationFrame and setInterval:

Using setInterval for animations forces the browser to refresh the screen when the related callback is triggered. That means, screen updates occur at any time, and have a good chance to be unnecessary. As a result the animations can be crude. Using rFA instead overcomes those "update interruptions". As the name says it requests an update frame. So, the browser becomes responsible to decide whether a callback is triggered, or not. Yes, he might decide not to trigger, for example if the updating page is not visible. The browser can synchronize the callback with its own refreshing rate, which is usually 60Hz, to avoid unnecessary (and CPU costly) repaints. Consequently, you get smoother results due to synchronized refreshes and can safe CPU resource (and battery life), especially while the screen is not visible.

That's why I simply do not care about frame rates when animate my stuff on the screen using rFA. The animations are updated in the correct time slot nearly all 16 ms. There are other articles out in the wild which explain more precisely how it works, like "Better performance with requestAnimationFrame", CreativeJS requestAnimationFrame , and "Better JavaScript animations with requestAnimationFrame". Also interesting is "Microsoft's rFA Testdrive", that compares both methods visually.