这是一款效果非常酷的 jQuery超酷文本和图标动画菜单特效插件。

HTML结构

html结构使用无序列表,每一个列表项都包含一个a元素,a元素中有三个用于动画的元素。

<ul id="sti-menu" class="sti-menu">
  <li data-hovercolor="#37c5e9">
    <a href="#">
      <h2 data-type="mText" class="sti-item">
        Some text
      </h2>
      <h3 data-type="sText" class="sti-item">
        Some more text
      </h3>
      <span data-type="icon" class="sti-icon sti-icon-care sti-item">
      </span>
    </a>
  </li>
  <li>...</li>
  ...
</ul>
                

data-hovercolor将被用来设置鼠标滑过时文本的颜色。同时我们也给标题元素和图标span一些data-type,以便在后面用jQuery来控制它们。

JAVASCRIPT

首先定义一些默认设置:

var settings = {
    // configuration for the mouseenter event
    animMouseenter      : {
        'mText' : {speed : 350, easing : 'easeOutExpo', delay : 140, dir : 1},
        'sText' : {speed : 350, easing : 'easeOutExpo', delay : 0, dir : 1},
        'icon'  : {speed : 350, easing : 'easeOutExpo', delay : 280, dir : 1}
    },
    // configuration for the mouseleave event
    animMouseleave      : {
        'mText' : {speed : 300, easing : 'easeInExpo', delay : 140, dir : 1},
        'sText' : {speed : 300, easing : 'easeInExpo', delay : 280, dir : 1},
        'icon'  : {speed : 300, easing : 'easeInExpo', delay : 0, dir : 1}
    },
    // speed for the item bg color animation
    boxAnimSpeed        : 300,
    // default text color (same defined in the css)
    defaultTextColor    : '#000',
    // default bg color (same defined in the css)
    defaultBgColor      : '#fff'
};
                

我们的每一个元素都有速度、easing效果、延时和方向(1为向上0为向下)。

return this.each(function() {
    // if options exist, lets merge them with our default settings
    if ( options ) {
        $.extend( settings, options );
    }
    var $el             = $(this),
        // the menu items
        $menuItems      = $el.children('li'),
        // save max delay time for mouseleave anim parameters
    maxdelay    = Math.max( settings.animMouseleave['mText'].speed + settings.animMouseleave['mText'].delay ,
                            settings.animMouseleave['sText'].speed + settings.animMouseleave['sText'].delay ,
                            settings.animMouseleave['icon'].speed + settings.animMouseleave['icon'].delay
                          ),
        // timeout for the mouseenter event
        // lets us move the mouse quickly over the items,
        // without triggering the mouseenter event
        t_mouseenter;
     
    // save default top values for the moving elements:
    // the elements that animate inside each menu item
    $menuItems.find('.sti-item').each(function() {
        var $el = $(this);
        $el.data('deftop', $el.position().top);
    });
    // Events
    ...
});
                

接下来为菜单项定义鼠标进入事件:

$menuItems.bind('mouseenter', function(e) {
     
    clearTimeout(t_mouseenter);
     
    var $item       = $(this),
        $wrapper    = $item.children('a'),
        wrapper_h   = $wrapper.height(),
        // the elements that animate inside this menu item
        $movingItems= $wrapper.find('.sti-item'),
        // the color that the texts will have on hover
        hovercolor  = $item.data('hovercolor');
     
    t_mouseenter    = setTimeout(function() {
        // indicates the item is on hover state
        $item.addClass('sti-current');
         
        $movingItems.each(function(i) {
            var $item           = $(this),
                item_sti_type   = $item.data('type'),
                speed           = settings.animMouseenter[item_sti_type].speed,
                easing          = settings.animMouseenter[item_sti_type].easing,
                delay           = settings.animMouseenter[item_sti_type].delay,
                dir             = settings.animMouseenter[item_sti_type].dir,
                // if dir is 1 the item moves downwards
                // if -1 then upwards
                style           = {'top' : -dir * wrapper_h + 'px'};
             
            if( item_sti_type === 'icon' ) {
                // this sets another bg image position for the icon
                style.backgroundPosition    = 'bottom left';
            } else {
                style.color                 = hovercolor;
            }
            // we hide the icon, move it up or down, and then show it
            $item.hide().css(style).show();
            clearTimeout($item.data('time_anim'));
            $item.data('time_anim',
                setTimeout(function() {
                    // now animate each item to its default tops
                    // each item will animate with a delay specified 
                    // in the options
                    $item.stop(true)
                         .animate({top : $item.data('deftop') + 'px'}, speed, easing);
                }, delay)
            );
        });
        // animate the bg color of the item
        $wrapper.stop(true).animate({
            backgroundColor: settings.defaultTextColor
        }, settings.boxAnimSpeed );
     
    }, 100);    
 
})
                

然后定义鼠标离开事件:

// mouseleave event for each menu item
.bind('mouseleave', function(e) {
     
    clearTimeout(t_mouseenter);
     
    var $item       = $(this),
        $wrapper    = $item.children('a'),
        wrapper_h   = $wrapper.height(),
        $movingItems= $wrapper.find('.sti-item');
     
    if(!$item.hasClass('sti-current')) 
        return false;       
     
    $item.removeClass('sti-current');
     
    $movingItems.each(function(i) {
        var $item           = $(this),
            item_sti_type   = $item.data('type'),
            speed           = settings.animMouseleave[item_sti_type].speed,
            easing          = settings.animMouseleave[item_sti_type].easing,
            delay           = settings.animMouseleave[item_sti_type].delay,
            dir             = settings.animMouseleave[item_sti_type].dir;
         
        clearTimeout($item.data('time_anim'));
         
        setTimeout(function() {
             
            $item.stop(true).animate({'top' : -dir * wrapper_h + 'px'}, speed, easing, function() {
                 
                if( delay + speed === maxdelay ) {
                     
                    $wrapper.stop(true).animate({
                        backgroundColor: settings.defaultBgColor
                    }, settings.boxAnimSpeed );
                     
                    $movingItems.each(function(i) {
                        var $el             = $(this),
                            style           = {'top' : $el.data('deftop') + 'px'};
                         
                        if( $el.data('type') === 'icon' ) {
                            style.backgroundPosition    = 'top left';
                        } else {
                            style.color                 = settings.defaultTextColor;
                        }
                         
                        $el.hide().css(style).show();
                    });
                     
                }
            });
        }, delay);
    });
});