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)

    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

    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
    Touch Premium Member
    Join Date
    Nov 2010
    Location
    Chicago
    Posts
    1,557
    Vote Rating
    341
    LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of LesJ has much to be proud of

      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 User
    Join Date
    Feb 2012
    Posts
    4
    Vote Rating
    0
    kushanratnayake is on a distinguished road

      0  

    Default Looks great!

    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
    392
    Vote Rating
    13
    murrah will become famous soon enough

      0  

    Default


    Nice! Thanks. Works perfectly.