Archive for November, 2012

ExtJS 4 bouncy box animation

Monday, November 5th, 2012

Do you know ExtJS has some nice animation features? Here it is a very simple notification box that “pops in” from outside the browser.

It is pretty straightforward – show a window outside the viewport and use the Window.animate() method. `animate` is inherited from AbstractComponent, so it is usable on all kinds of components.
However, there is one gotcha. If you initially render the window on the right or bottom outside the screen (i.e. coordinates 10000,10000) the viewport will slide to keep the shown window in focus. I’m not sure why it does it. So, we do it a bit tricky – first show the window with negative coordinates (viewport will not slide in that way) and second – ensure the window is really shown before attempting to do `setPosition()` or `animate()`. According to the docs `showAt()` should return `this` and be chainable, but in my testing invironment it returns undefined… I’ve put a dumb setTimeout() – don’t do that if you have choice – chain showAt() or use onShow listener.

Using my sample code you should first create a NS.TestAnimationBox component and then do a `createWindow()` on it.

Ext.define('NS.TestAnimationBox', {
    extend: 'Ext.window.Window',
    width: 250,
    height: 150,
    layout: 'fit',
    title: 'Reminder',

    constructor: function(cfg){
        this.initConfig(cfg)
        this.items = this.getItems();
        this.callParent(arguments);

        var me = this;

        me.showAt(-2000, -2000); // initial 'show' outside browser
    },

    slide: function(){
        var me = this;
        var iViewHeight = Ext.getBody().getViewSize().height;
        var iViewWidth = Ext.getBody().getViewSize().width;

        me.setPosition(iViewWidth + me.width - 10, iViewHeight - me.height - 40); // adjust position just outside on the right
        me.animate({
            duration: 750,
            easing: 'bounce-out',
            to: {
                x: iViewWidth - me.width - 10
            }
        })
    },

    getItems: function(){
        var me = this;

        return [
            {
                bodyPadding: 10,
                html: 'Some text here',
                buttons: [
                    {
                        text: 'Reset',
                        handler: function(){
                            me.slide();
                        }
                    },{
                        text: 'Close',
                        handler: function(){
                            me.setPosition(-2000, -2000);
                        }
                    }
                ]
            }
        ]
    },

    createWindow: function(){
        var me = this;

        setTimeout(function(){
            me.slide();
        }, 100); // just to be sure there it is time interval between showing and sliding
    }

});