这是一款非常效果非常炫酷的jQuery和css3全屏导航菜单圆形气泡动画特效插件。所有的现代浏览器都支持这个特效。在插件中我们集成了 Velocity.js

HTML结构

html结构使用一个无序列表作为导航菜单。 .cd-overlay-nav.cd-overlay-content是用来做圆形气泡动画的层。它们被放置到右上角的导航菜单按钮的后面,它们里面的两个span是两种不同颜色的圆形展开效果。 .cd-nav-trigger是用于触发菜单的导航按钮。

<header>
  <a class="cd-logo" href="#0"><img src="img/cd-logo.svg" alt="Logo"></a>
</header>
 
<nav>
  <ul class="cd-primary-nav">
    <li><a href="#0">The team</a></li>
    <li><a href="#0">Our services</a></li>
    <li><a href="#0">Our projects</a></li>
    <li><a href="#0">Start a project</a></li>
    <li><a href="#0">Join In</a></li>
    <li><a href="#0">Create an account</a></li>
  </ul>
</nav>
 
<main class="cd-content">
  <!-- your content here -->
</main> 
 
<div class="cd-overlay-nav">
  <span></span>
</div> <!-- cd-overlay-nav -->
 
<div class="cd-overlay-content">
  <span></span>
</div> <!-- cd-overlay-content -->
 
<a href="#0" class="cd-nav-trigger">Menu<span class="cd-icon"></span></a>
                

CSS样式

当你查看CSS文件时,你会发现导航按钮时固定在右上角的position:fixed 。为了使这个特效能够正常工作,我们将两个圆形动画层(.cd-overlay-nav.cd-overlay-content)居中并放置在触发按钮后面的正确位置上。为了做到这一点,我们需要为它们定义固定的宽度和高度。但是你注意观察<span>元素,它实际上是圆形动画元素,你会注意到,我们没有定义任何的位置或大小值。因为圆形衣架覆盖了整个屏幕,不论窗口大小,我们只需要在jQuery中定义positioning 和width即可。

.cd-nav-trigger {
  top: 18px;
  right: 5%;
  height: 44px;
  width: 44px;
  z-index: 5;
  /* image replacement */
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
}
.cd-overlay-nav, .cd-overlay-content {
  /* containers of the 2 main rounded backgrounds - these containers are used to position the rounded bgs behind the menu icon */
  position: fixed;
  top: 18px;
  right: 5%;
  height: 4px;
  width: 4px;
  transform: translateX(-20px) translateY(20px);
}
.cd-overlay-nav span, .cd-overlay-content span {
  display: inline-block;
  position: absolute;
  border-radius: 50%;
  will-change: transform;
  transform: scale(0);
}
                

在点击触发按钮后,我们希望它产生一些动画效果,而不是立刻转变为关闭按钮。所以我们添加了一个<span>元素.cd-icon,这样我们就可以使用它的::before::after伪元素来制作动画效果。

.cd-nav-trigger .cd-icon {
  /* icon created in CSS */
  position: absolute;
  left: 50%;
  top: 50%;
  bottom: auto;
  right: auto;
  transform: translateX(-50%) translateY(-50%);
  display: inline-block;
  width: 18px;
  height: 3px;
  background-color: #ffffff;
  z-index: 10;
}
.cd-nav-trigger .cd-icon::before, .cd-nav-trigger .cd-icon:after {
  /* upper and lower lines of the menu icon */
  position: absolute;
  top: 0;
  right: 0;
  width: 100%;
  height: 100%;
  background-color: inherit;
  transition: transform .3s;
}
.cd-nav-trigger .cd-icon::before {
  transform: translateY(-6px) rotate(0deg);
}
 
.cd-nav-trigger .cd-icon::after {
  transform: translateY(6px) rotate(0deg);
}
.cd-nav-trigger.close-nav .cd-icon {
  /* user clicks on the .cd-nav-trigger element - transform the icon */
  background-color: rgba(255, 255, 255, 0);
}
.cd-nav-trigger.close-nav .cd-icon::before, .cd-nav-trigger.close-nav .cd-icon::after {
  background-color: white;
}
.cd-nav-trigger.close-nav .cd-icon::before {
  transform: translateY(0) rotate(45deg);
}
.cd-nav-trigger.close-nav .cd-icon::after {
  transform: translateY(0) rotate(-45deg);
}
                

导航菜单,背景颜色的编号和他们的动画效果都带有一定的延时,我们通过2个伪元素来制作这种效果:

.cd-nav-trigger::before, .cd-nav-trigger::after {
  /* 2 rounded colored backgrounds for the menu icon */
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  height: 100%;
  width: 100%;
  transition-property: transform;
}
.cd-nav-trigger::before {
  background-color: #091d23;
  transform: scale(1);
  transition-duration: 0.3s;
  transition-delay: 0.4s;
}
.cd-nav-trigger::after {
  background-color: #ffb441;
  transform: scale(0);
  transition-duration: 0s;
  transition-delay: 0s;
}
.cd-nav-trigger.close-nav::before {
  /* user clicks on the .cd-nav-trigger element - 1st rounded background disappears */
  transform: scale(0);
}
.cd-nav-trigger.close-nav::after {
  /* user clicks on the .cd-nav-trigger element - 2nd rounded background appears */
  transform: scale(1);
  transition-duration: 0.3s;
  transition-delay: 0.4s;
}
                

JAVASCRIPT

当用户点击了导航按钮,我们使.cd-overlay-nav中的<span>元素开始动画,当圆形气泡填充满整个屏幕,将显示导航菜单。当用户再次点击导航按钮来关闭导航菜单时,我们使 .cd-overlay-content中的<span>元素开始动画,在动画结束时,我们隐藏第一个圆形和菜单,它们将会因为被设置很低的z-index而不可见。最后,我们减少第二个圆形(黄色的那个)的透明度,从而使下面的内容显示出来。

在jQuery中,我们使用span class="m"> initLayer()

函数来定义<span>元素的 position 和 size。我们指定了一个高度等于视口对角线的两倍,top和left等于负的视口对角线值。

当用户点击了触发按钮,我们使.cd-overlay-nav span元素开始动画,改变它的scale值从0到1。(我们使用 Velocity.js 来制作这个动画效果。)

var overlayNav = $('.cd-overlay-nav'),
  toggleNav = $('.cd-nav-trigger'),
  navigation = $('.cd-primary-nav');
 
toggleNav.on('click', function(){
  if(!toggleNav.hasClass('close-nav')) {
    //animate menu icon into a cross icon
    toggleNav.addClass('close-nav');
    //animate the navigation layer
    overlayNav.children('span').velocity({
      translateZ: 0,
      scaleX: 1,
      scaleY: 1,
    }, 500, 'easeInCubic', function(){
      //show navigation
      navigation.addClass('fade-in');
    });
  }
}
                

当用户点击了关闭按钮,我们修改.cd-overlay-content spanscale值。

var overlayNav = $('.cd-overlay-nav'),
  overlayContent = $('.cd-overlay-content'),
  toggleNav = $('.cd-nav-trigger'),
  navigation = $('.cd-primary-nav');
 
toggleNav.on('click', function(){
  if(!toggleNav.hasClass('close-nav')) {
    //it means navigation is not visible yet - open it and animate navigation layer
    //....
  } else {
    //animate cross icon into a menu icon
    toggleNav.removeClass('close-nav');
    //animate the content layer
    overlayContent.children('span').velocity({
      translateZ: 0,
      scaleX: 1,
      scaleY: 1,
    }, 500, 'easeInCubic', function(){
      //hide navigation
      navigation.removeClass('fade-in');
      //scale to zero the navigation layer
      overlayNav.children('span').velocity({
        translateZ: 0,
        scaleX: 0,
        scaleY: 0,
      }, 0);
      //reduce to opacity of the content layer with the is-hidden class
      overlayContent.addClass('is-hidden').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
        //wait for the end of the transition and scale to zero the content layer
        overlayContent.children('span').velocity({
          translateZ: 0,
          scaleX: 0,
          scaleY: 0,
        }, 0, function(){overlayContent.removeClass('is-hidden')});
 
      });
    });
  }
});