1. #1
    Sencha Premium Member
    Join Date
    Aug 2007
    Posts
    22
    Vote Rating
    3
    mlavender is on a distinguished road

      2  

    Default Card Layout Crossfade Override (ExtJS 4.2)

    I've seen a lot of posts about animating transitions with the card layout and had a working version in 3.4 (which I lost when we upgraded to 4.x), but finally got working again. This is set up to animate by doing a crossfade where the active panel fades out while the new one fades in. It's done as an override to the default behavior, but could easily be modified to be either a new ux class or to be configurable. In my case, we like it effect so we're using it globally. It could also pretty easily be modified to do a slide transition (rather than fade), simply by changing the animation.

    In any case, hope someone finds it useful!

    Code:
    // Add ability to crossfade cards when switching active one.
    Ext.override(Ext.layout.CardLayout, {
        setActiveItem: function(newCard) {
            var me = this,
                owner = me.owner,
                oldCard = me.activeItem,
                rendered = owner.rendered,
                newIndex;
    
            newCard = me.parseActiveItem(newCard);
            newIndex = owner.items.indexOf(newCard);
    
            if (newIndex == -1) {
                newIndex = owner.items.items.length;
                Ext.suspendLayouts();
                newCard = owner.add(newCard);
                Ext.resumeLayouts();
            }
    
            if (newCard && oldCard != newCard) {
                if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
                    return false;
                }
                if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
                    return false;
                }
    
                if (rendered) {
                    Ext.suspendLayouts();
    
                    if (!newCard.rendered) {
                        me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
                    }
    
                    if (oldCard) {
                        if (me.hideInactive) {
                            oldCard.getEl().stopAnimation();
                            oldCard.getEl().animate({
                                duration: 500,
                                from: { opacity: 1 },
                                to: { opacity: 0 },
                                listeners: {
                                    afteranimate: function() {
                                        oldCard.hide();
                                        oldCard.getEl().setDisplayed('none');
                                    }
                                }
                            });
    
                            oldCard.hiddenByLayout = true;
                        }
                        oldCard.fireEvent('deactivate', oldCard, newCard);
                    }
    
                    newCard.getEl().stopAnimation();
                    if (newCard.hidden) {
                        newCard.show();
                        newCard.getEl().setStyle({
                            position: 'absolute',
                            opacity: 0,
                            top: 0
                        });
    
                        newCard.getEl().animate({
                            duration: 500,
                            from: { opacity: 0 },
                            to: { opacity: 1 },
                            listeners: {
                                afteranimate: function() {
                                    newCard.getEl().setStyle({ position: '' });
                                }
                            }
                        });
                    }
    
                    me.activeItem = newCard;
    
                    Ext.resumeLayouts(true);
                } else {
                    me.activeItem = newCard;
                }
    
                newCard.fireEvent('activate', newCard, oldCard);
    
                return me.activeItem;
            }
            return false;
        }
    });

  2. #2
    Sencha User
    Join Date
    May 2013
    Posts
    8
    Vote Rating
    1
    m0r14rty is on a distinguished road

      1  

    Default Awesome

    Looks great, using it right now with zero issues. Really needed something to give this app a little kick and this was perfect.

  3. #3
    Sencha Premium User
    Join Date
    Nov 2010
    Location
    Chicago
    Posts
    1,681
    Vote Rating
    491
    LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future LesJ has a brilliant future

      2  

    Default

    I modified the code. Instead of overriding the Card layout, I created a new subclass called crossfadecard layout.

    Change MyApp.view.CrossfadeCard class name to fit your application.

    Code:
    Ext.define('MyApp.view.CrossfadeCard', {
        extend: 'Ext.layout.container.Card',
    
    
        alias: 'layout.crossfadecard',
    
    
        setActiveItem: function(newCard) {
            var me = this,
                owner = me.owner,
                oldCard = me.activeItem,
                rendered = owner.rendered,
                newIndex;
    
    
            newCard = me.parseActiveItem(newCard);
            newIndex = owner.items.indexOf(newCard);
    
    
            // If the card is not a child of the owner, then add it.
            // Without doing a layout!
            if (newIndex == -1) {
                newIndex = owner.items.items.length;
                Ext.suspendLayouts();
                newCard = owner.add(newCard);
                Ext.resumeLayouts();
            }
    
    
            // Is this a valid, different card?
            if (newCard && oldCard != newCard) {
                // Fire the beforeactivate and beforedeactivate events on the cards
                if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
                    return false;
                }
                if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
                    return false;
                }
    
    
                if (rendered) {
                    Ext.suspendLayouts();
    
    
                    // If the card has not been rendered yet, now is the time to do so.
                    if (!newCard.rendered) {
                        me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
                    }
    
    
                    if (oldCard) {
                        if (me.hideInactive) {
                            // oldCard.hide();
                            me.hideOldCard(oldCard);
                            oldCard.hiddenByLayout = true;
                        }
                        oldCard.fireEvent('deactivate', oldCard, newCard);
                    }
                    // Make sure the new card is shown
                    if (newCard.hidden) {
                        newCard.show();
                        me.showNewCard(newCard);
                    }
    
    
                    // Layout needs activeItem to be correct, so set it if the show has not been vetoed
                    if (!newCard.hidden) {
                        me.activeItem = newCard;
                    }
                    Ext.resumeLayouts(true);
                } else {
                    me.activeItem = newCard;
                }
    
    
                newCard.fireEvent('activate', newCard, oldCard);
    
    
                return me.activeItem;
            }
            return false;
        },
        // @private
        hideOldCard: function (card) {
            card.getEl().stopAnimation();
            card.getEl().animate({
                duration: 500,
                from: { opacity: 1 },
                to: { opacity: 0 },
                listeners: {
                    afteranimate: function() {
                        card.hide();
                        card.getEl().setDisplayed('none');
                    }
                }
            });
        },
        // @private    
        showNewCard: function (card) {
            card.getEl().setStyle({
                position: 'absolute',
                opacity: 0,
                top: 0
            });
            card.getEl().animate({
                duration: 500,
                from: { opacity: 0 },
                to: { opacity: 1 },
                listeners: {
                    afteranimate: function() {
                        card.getEl().setStyle({ position: '' });
                    }
                }
            });
        }
    });

  4. #4
    Sencha Premium Member
    Join Date
    Feb 2012
    Posts
    4
    Vote Rating
    0
    kushanratnayake is on a distinguished road

      0  

    Default Looks great!

    Thanks mlavender and LesJ for sharing!

  5. #5
    Sencha User murrah's Avatar
    Join Date
    Oct 2007
    Location
    Katoomba, Blue Mountains, west of Sydney, Australia
    Posts
    395
    Vote Rating
    13
    murrah will become famous soon enough

      0  

    Default

    Nice! Thanks. Works perfectly.