给你的移动网站加点料:移动旋转菜单的实现方案

  在github上看到有人用HTML5 + CSS3 + Javascript实现了jQuery Wheel Menu(旋转菜单),因为本人供职于移动网站的开发,又不是一个专业的前端开发,所以看到这么炫的东东肯定就垂涎三尺,想移植到移动平台,当然最好一句代码不修改直接移植过来是最省事的,但是最终发现此大牛给出的Demo在移动端上展现是有一定问题的,所以在边看中国好声音的过程中,修改了他的一部分代码,实现了在移动浏览器上可以自由使用的jQuery Wheel Menu(旋转菜单)。

  既然实现了如此绚丽的菜单,那么在移动网站上究竟在怎么样的场景下可以使用呢?其实,淘宝移动主站(m.taobao.com)左下角的“淘”就是这样一个类似的效果,但是淘宝主站实现的一些绚丽效果有一个让人头疼的问题,就是在移动端没问题,但是在PC端上就是没有任何效果。也许专业的前端能够接受这件事情,毕竟人家做的移动网站和PC无关的。不过因为本人是一个半路出家的很不专业的假“前端”开发工程师,所以我希望在移动端上实现的一些绚丽效果当用PC浏览器访问的时候,用鼠标点击代替移动端手指Tap的时候,也同样看到类似的效果。所以,这次玩的jQuery Wheel Menu在移动端和PC端的浏览器上不管你是Click还是Tap都是可以玩的。

  那这种旋转式的菜单到底什么场景下使用呢?还不知道吗?我都举例淘宝了,当然你去看一看嘛,哈哈~这种旋转式菜单适合fixed在页面的左下角或者右下角,将回首页、消息通知、登录、个人中心等此类公共功能放入其中,这样不管你在哪个网页上,想回到这些公共功能的时候,只要点一下左下角或者右下角的这么个小东西,就可以立刻过去。

  在线演示地址:http://sandbox.runjs.cn/show/lmfucabu

  你也可以拿出手机扫描下方二维码,直接在手机上进行效果演示:

  

  先来几张页面截图吧。

  这个控件的实现上主要使用了CSS3的动画实现方式,各位有兴趣的同学,可以借助这个例子来很好地了解一下CSS3的动画实现方式。好了,废话不多说了,直接上代码吧!

Javascript代码:jquery.wheelmenu.js

对Javascript代码没有进行改动,我之所以说自己是个“假”前端就是因为我很不“喜欢”去写Javascript,所以我使用了github上的源码。

!function($){
  
  var defaults = {
        trigger: "click",
        animation: "fade",
        angle: [0,360],
        animationSpeed: "medium"
    };

    $.fn.centerAround = function (button) {
    var offset = button.offset(),
        width = button.outerWidth(),
        height = button.outerHeight(),
        buttonX = (offset.left - $(document).scrollLeft() ) + width / 2,
        buttonY = (offset.top -  $(document).scrollTop() ) + height / 2,
        objectOffset = this.offset();
        // alert(width);
        // alert(height);
        // alert(buttonX);
        // alert(buttonY);
    this.css("position","fixed");
    this.css("top", buttonY  - (this.outerHeight() / 2)  + "px");
    this.css("left", buttonX - (this.outerWidth() / 2)   + "px");
    return this;
  }
  
  $.fn.flyIn = function (el, button, width, height, angle, step, radius, settings) {
    var d = 0;
    this.stop(true,true);
    this.each(function(index) {
      angle = (settings.angle[0] + (step * index)) * (Math.PI/180); 
      var x = Math.round(width/2 + radius * Math.cos(angle) - $(this).find("a").outerWidth()/2),
          y = Math.round(height/2 + radius * Math.sin(angle) - $(this).find("a").outerHeight()/2);
      $(this).animateRotate(360).css({
          position: 'absolute',
          opacity: 0,
          left: "50%",
          top: "50%",
          marginLeft: "-" + $(this).outerWidth() / 2,
          marginTop: "-" + $(this).outerHeight() / 2
      }).delay(d).animate({
        opacity:1,
        left: x + 'px',
        top: y + 'px'
      }, settings.animationSpeed[1]);
      d += settings.animationSpeed[0];
    });
  }
  
  $.fn.flyOut = function (el, button) {
    var d = 0;
    this.stop(true,true);
    $(this.get().reverse()).each(function() {
        $(this).animateRotate(-360).delay(d).animate({
          opacity:0,
          left: el.outerWidth() / 2 + "px",
        top: el.outerHeight() / 2 + "px"
        }, 150);
      d += 15;
      }).promise().done( function() {
      el.removeClass("active").css("visibility", "hidden").hide();
      button.removeClass("active")
    });
  }
  
  $.fn.fadeInIcon = function (el, button, width, height, angle, step, radius, settings) {
    var d = 0;
    this.stop(true,true);
    this.each(function(index) {
      angle = (settings.angle[0] + (step * index)) * (Math.PI/180); 
      var x = Math.round(width/2 + radius * Math.cos(angle) - $(this).find("a").outerWidth()/2),
          y = Math.round(height/2 + radius * Math.sin(angle) - $(this).find("a").outerHeight()/2);
      $(this).css({
          position: 'absolute',
          left: x + 'px',
          top: y + 'px',
          opacity: 0
      }).delay(d).animate({opacity:1}, settings.animationSpeed[1]);
      
      d += settings.animationSpeed[0];
    });
  }
  
  $.fn.fadeOutIcon = function (el, button) {
    var d = 0;
    this.stop(true,true);
    
    $(this.get().reverse()).each(function() {
        $(this).delay(d).animate({opacity:0}, 150);
      d += 15;
      }).promise().done( function() {
      el.removeClass("active").css("visibility", "hidden").hide();
      button.removeClass("active")
    });
  }

    $.fn.hideIcon = function (button, settings) {
      var fields = this.find(".item"),
          el = this;
      switch (settings.animation) { 
      case 'fade': 
        fields.fadeOutIcon(el, button)
        break; 
    
      case 'fly': 
        fields.flyOut(el, button)
        break; 
    }

    }

    $.fn.showIcon = function (button, settings) {
      var el = this,
          zindex = '6';
      if (settings.trigger == "hover") {
        var zindex = '3';
    }
      button.addClass("active").css({
      'z-index': zindex
    });
    
    
    
      el.show().css({
        position: 'absolute',
        'z-index': '5',
        'padding': '30px' // add safe zone for mouseover
    }).centerAround(button); 
    el.addClass("wheel active").css("visibility", "visible").show();

      if (el.attr('data-angle')) {
      settings.angle = el.attr('data-angle')
    }
    
    settings = predefineAngle(settings);
      var radius = el.width() / 2,
      fields = el.find(".item"),
      container = el,
      width = container.innerWidth(),
      height = container.innerHeight(),
      angle =  0,
      step = (settings.angle[1] - settings.angle[0]) / fields.length;
     
     
      switch (settings.animation) { 
        case 'fade': 
          fields.fadeInIcon(el, button, width, height, angle, step, radius, settings)
          break; 
          
        case 'fly': 
          fields.flyIn(el, button, width, height, angle, step, radius, settings)
          break; 
      }
    
    }

    $.fn.animateRotate = function(angle, duration, easing, complete) {
      return this.each(function() {
          var $elem = $(this);

          $({deg: 0}).animate({deg: angle}, {
              duration: duration,
              easing: easing,
              step: function(now) {
                  $elem.css({
                      transform: 'rotate(' + now + 'deg)'
                  });
              },
              complete: complete || $.noop
          });
      });
  };
  

    function predefineAngle (settings) {
      var convert = false
      if ($.type(settings.angle) == "string") {
        try {
        if (eval(settings.angle).length > 1) convert = true
      }
      catch(err) {
        convert = false
      }
        if (convert == true) {
          settings.angle = JSON.parse(settings.angle);
        } else {
          switch (settings.angle) { 
          case 'N':
            settings.angle = [180,380]
            break;
          case 'NE':
            settings.angle = [270,380]
            break;
          case 'E':
            settings.angle = [270,470]
            break;
          case 'SE':
            settings.angle = [360,470]
            break;
          case 'S':
            settings.angle = [360,560]
            break;
          case 'SW':
            settings.angle = [90,200]
            break;
          case 'W':
            settings.angle = [90,290]
            break;
          case 'NW':
            settings.angle = [180,290]
            break;
          case 'all':
            settings.angle = [0,360]
            break;
        }
        } 
    }
    return settings;
    }

    function predefineSpeed(settings) {
      if ($.type(settings.animationSpeed) == "string") { 
      switch (settings.animationSpeed) { 
        case 'slow':
          settings.animationSpeed = [75,700]
          break;
        case 'medium':
          settings.animationSpeed = [50,500]
          break;
        case 'fast':
          settings.animationSpeed = [25,250]
          break;
        case 'instant':
          settings.animationSpeed = [0,0]
          break;
      }
    }
    return settings;
    }
  
  $.fn.wheelmenu = function(options){
    var settings = $.extend({}, defaults, options);
    
    settings = predefineSpeed(settings);
    
    return this.each(function(){
      var button = $(this)
      var el = $($(this).attr("href"));
      el.addClass("wheel");
      
      button.css("opacity", 0).animate({
        opacity: 1
      })
      if (settings.trigger == "hover") {

        button.bind({
          mouseenter: function() {
            el.showIcon(button, settings);
          }
        });
        
        el.bind({
          mouseleave: function() {
            el.hideIcon(button, settings);
          }
        });
        
      } else {
        button.click( function() {
          if (el.css('visibility') == "visible") {
            el.hideIcon(button, settings);
          } else {
            el.showIcon(button, settings);
          }
        });
      }
    });
  }
  
}(window.jQuery);

CSS代码:wheelmenu.css

我对CSS的代码是比较有兴趣玩的,所以并没有完全使用作者的CSS代码以及代码结构,因为我觉得作者的CSS代码在规范性上还是存在一定问题的(提供了CSS文件,但是在Demo的html中又写了很大一段代码,这种规范向来都是我鄙视的,鄙视一下大拿作者,来提升一下自己吧,哈哈~)

body {
  background: #C1FFC1;
  padding: 0;
  text-align: center;
  position: relative;
  margin: 0;
}

a {
  text-decoration: none;
}

.main {
  width: 100%;
  margin: 0 auto;
}

h1 {
  font-family: 'Pacifico', cursive;
  margin: 10px;
  width: 100%;
  color: #CD2626;
}

.wheel-button {
  position: relative;
  line-height: 35px;
  font-weight: bold;
  font-size: 35px;
  background: #FF7300;
  padding: 10px;
  text-align: center;
  border-radius: 50px;
  width: 35px;
  height: 35px;
  color: white;
  display: block;
  margin: 20px auto 20px;
  border: 1px solid #cccccc;
  box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

.wheel-button span, .wheel span{
  position: relative;
  -moz-transition: all 1s ease;
  -webkit-transition: all 1s ease;
  -o-transition: all 1s ease;
  transition: all 1s ease;
  display: block;
}

.wheel-button.active span{
  transform: rotate(135deg);
  -ms-transform: rotate(135deg); /* IE 9 */
  -webkit-transform: rotate(135deg); /* Safari and Chrome */
}

.pointer {
  color: #836FFF;
  font-family: 'Pacifico', cursive;
  font-size: 30px;
  height: 30px;
  line-height: 30px;
  margin: 10px 0 0px 0;
}

.wheel {
  margin: 0;
  padding: 0;
  list-style: none;
  width: 200px; /* this will determine the diameter of the circle */
  height: 200px; /* this will determine the diameter of the circle */
  visibility: hidden;
  position: relative;
  display: none;
}

.wheel li {
  overflow: hidden;
  float:left;
}

.wheel li a {
  display: block;
  background: rgba(0,0,0,0.5);
  border-radius: 50px;
  font-weight: bold;
  padding: 10px;
  text-align: center;
  width: 20px;
  height: 20px;
  border: 1px solid #ffffff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  color: white;
  -moz-transition: all 0.25s ease;
  -webkit-transition: all 0.25s ease;
  -o-transition: all 0.25s ease;
  transition: all 0.25s ease;
}
    
.wheel-button.ne {
  border-color: white;
  background: #1ABC9C;
  color: #34FFFF;
  position: fixed;
  bottom: 10px;
  left: 10px;
}
    
.wheel-button.nw {
  border-color: white;
  background-color: #E67E22;
  color: #FFFC44;
  position: fixed;
  bottom: 10px;
  right: 10px;
}

Demo Html代码:wheelmenu.html

一个简单的移动页面的示例代码结构,我对视觉设计欠缺,所以Demo页面各位注重事先的效果就可以了。

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
    <title>jQuery Wheel Menu On Mobile</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
      <script type="text/javascript" src="jquery.wheelmenu.js"></script>
    <link rel="stylesheet" type="text/css" href="wheelmenu.css" />
    <script>
        addEventListener("load", function() { setTimeout(scrollTo, 0, 0, 0); }, false);
          $(document).ready(function(){
            $(".wheel-button").wheelmenu({
        trigger: "click",
        animation: "fly",
        animationSpeed: "fast"
      });
        });

    </script>
</head>
<body>
    <div class="main">
        <h1>jQuery Wheel Menu On Mobile</h1>
        <div class="pointer">Touch me, please!</div>
        <a href="#wheel" class="wheel-button">
            <span>+</span>
        </a>
        <ul id="wheel"  data-angle="all">
            <li class="item"><a href="#home">A</a></li>
            <li class="item"><a href="#home">B</a></li>
            <li class="item"><a href="#home">C</a></li>
            <li class="item"><a href="#home">D</a></li>
            <li class="item"><a href="#home">E</a></li>
            <li class="item"><a href="#home">F</a></li>
            <li class="item"><a href="#home">G</a></li>
            <li class="item"><a href="#home">H</a></li>
            <li class="item"><a href="#home">I</a></li>
            <li class="item"><a href="#home">J</a></li>
        </ul>
      
        <a href="#wheel2" class="wheel-button ne">
           <span>+</span>
          </a>
        <ul id="wheel2" data-angle="NE" class="wheel">
            <li class="item"><a href="#home">A</a></li>
            <li class="item"><a href="#home">B</a></li>
            <li class="item"><a href="#home">C</a></li>
            <li class="item"><a href="#home">D</a></li>
        </ul>
      
        <a href="#wheel3" class="wheel-button nw">
           <span>+</span>
          </a>
        <ul id="wheel3" data-angle="NW" class="wheel">
            <li class="item"><a href="#home">A</a></li>
            <li class="item"><a href="#home">B</a></li>
            <li class="item"><a href="#home">C</a></li>
            <li class="item"><a href="#home">D</a></li>
        </ul>
    </div>
</body>
</html>

 

posted @ 2013-08-31 22:27  九朗的码农生活  阅读(1675)  评论(7编辑  收藏  举报