看到一個很棒的菜單效果,分享一下
原文 3D滾動下拉菜單-簡直不要太任性javascript
http://runjs.cn/detail/re75abbwcss
最初看到這個是在14年5月,猛戳這裏:妙味官網
,以爲很是炫。想要作出來,因此就開始學習web。html
那時候是作c/s的,也由於這個走上了b/s之路, 如今先後臺都要寫了。java
前幾天又來試試,發現本身能大概實現了,好屌。jquery
由於平時主要是實現功能,因此可能一些代碼習慣,實現方式不太好,但願指出來。css3
我也是一個菜鳥,會的很少( ̄∇ ̄),就不在這裏show無知了,主要涉及到:transform
,transform-style(IE不支持?)
web
能夠參見:Transform-style和Perspective屬性算法
你們玩一玩這個菜單,會看到它不是勻速展開的,而是在展開動做的末尾「抖」一下學習
這個涉及到算法...我我的僅做了解(就是隻知道這個東西,怎麼實現不知道)動畫
各類緩動效果和更詳細的說明:JavaScript Tween算法及緩動效果
jquery有animate方法,能夠很是方便的實現動畫,原理是實時改變節點的樣式
。
附:使用jquery的animate實現的動畫,節點最好不要設置css3的transition,有衝突
我看到jquery的動畫也不是勻速改變,因而查了一下資料,確實也有這個緩動算法,默認只有兩種:linear勻速
,swing慢-快-慢
,添加擴展方法來實現(如2中連接緩動實例的 easeOutBack):慢-中-快-太快致使超過了-返回到正確的位置
,專業術語爲:超過範圍的三次方緩動
:
jQuery.extend(jQuery.easing, { easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; } })
jQuery的animate動畫,我之前不知道在哪裏看到的:只能實現能夠用數字表示的動畫。也就是說css3的transform是不行的。可是animate有一種重載!
經常使用的方式:
$("html,body").animate({ scrollTop: "0px" }, 1000);
另外一種重載:
$({ num: 32 }).animate({ num: 64 }, { duration:1000, step: function () { console.log("當前的num是:" + this.num); }, complete: function () { console.log("結束了,num是:" + this.num); } });
哈哈,看到這個你們就有思路了吧:
根據要改變的樣式定義一個對象,利用animate改變這個對象,監聽step和complete事件來拼接新的樣式賦值給你要執行動畫的元素!
在妙味官網上面看了好久都不知道從何看起,把這個作出來以後看到博友 呂大豹 將妙味的代碼扒出來了,艹,仍是沒看懂。
如下是3D下拉菜單的代碼:
HTML :
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>RunJS</title> <script type="text/javascript" class="library" src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> </head> <body> <div id="fold_box" class="P800"> <div id="fold" class="T3D fold_pager"> <h2>3D下拉菜單</h2> <div id="fold_list" class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> <div class="T3D fold_pager" style="transform: rotateX(-180deg); -webkit-transform: rotateX(-180deg);"> <a href="#">基於 - jquery+緩動</a> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </body> </html>
JavaScript :
//添加緩動擴展 jQuery.extend(jQuery.easing,{ easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; } }) var pageArr; function rotateDown(index) { if (index < 0 || index >= pageArr.length) { return; } var ele = pageArr.eq(index); ele.children("a").css("background-color", "#fff"); var obj = ele.data("obj"); if (!obj) { ele.data("obj", { r: getNumByEle(ele) }); obj = ele.data("obj"); } else obj.r = getNumByEle(ele); $(obj).animate({ r: 0 }, { duration: 1000, easing: "easeOutBack", step: function () { ele.css({ "-moz-transform": "rotateX(" + this.r + "deg)", "-webkit-transform": "rotateX(" + this.r + "deg)", "-0-transform": "rotateX(" + this.r + "deg)", "-ms-transform": "rotateX(" + this.r + "deg)", "transform": "rotateX(" + this.r + "deg)" }); //根據偏移量判斷是否展開下一個 if (ele.data("opening")) return; //已經開始摺疊下一個了 var rotateOff = getNumByEle(ele); if (rotateOff > -120) { ele.data("opening", true); rotateDown(index + 1); } }, complete: function () { ele.css({ transform: "rotateX(0deg)" }); } }); } function rotateUp(index) { if (index < 0 || index >= pageArr.length) { return; } var ele = pageArr.eq(index); ele.children("a").css("background-color", "rgb(223,223,223)"); var obj = ele.data("obj"); if (!obj) { ele.data("obj", { r: getNumByEle(ele) }); obj = ele.data("obj"); } else obj.r = getNumByEle(ele); $(obj).animate({ r: -180 }, { duration: 600, easing: "linear", step: function () { ele.css({ "-moz-transform": "rotateX(" + this.r + "deg)", "-webkit-transform": "rotateX(" + this.r + "deg)", "-0-transform": "rotateX(" + this.r + "deg)", "-ms-transform": "rotateX(" + this.r + "deg)", "transform": "rotateX(" + this.r + "deg)" }); //根據偏移量判斷是否摺疊上一個 if (ele.data("closing")) return; //已經開始摺疊上一個了 var rotateOff = getNumByEle(ele); if (rotateOff < -60) { ele.data("closing", true); rotateUp(index - 1); } }, complete: function () { ele.css({ transform: "rotateX(-180deg)" }); } }); } function getNumByEle(ele) { var rotateStyle = ele.attr("style"); return rotateStyle.match(/rotateX\(([-]?\d+)/)[1]; } function stopAll() { for (var i = 0; i < pageArr.length; i++) { var ele = pageArr.eq(i); ele.data("opening", false); ele.data("closing", false); var obj = ele.data("obj"); if (obj && $(obj).stop) { $(obj).stop(true, false); } } } $(function(){ pageArr = $("#fold .fold_pager"); $("#fold").mousemove(function (e) { //Y軸旋轉 var el = e.clientX - $(this).offset().left; var off = 60 * el / $(this).width() - 30; //this.style.transform = "rotateY(" + off + "deg)"; $(this).css({ "-webkit-transform":"rotateY(" + off + "deg)", "-moz-transform":"rotateY(" + off + "deg)", "-ms-transform":"rotateY(" + off + "deg)", "-o-transform":"rotateY(" + off + "deg)", "transform":"rotateY(" + off + "deg)" }); }).mouseenter(function () { //展開 stopAll(); rotateDown(0); }).mouseleave(function () { //摺疊 stopAll(); rotateUp(pageArr.length - 1); }); });
CSS :
*{ box-sizing: border-box; } .P800 { -webkit-perspective: 800px; -moz-perspective: 800px; -ms-perspective: 800px; perspective: 800px; } .T3D { -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; } body{ background: #fff url(http://www.miaov.com/2013/css/bg/bg1.jpg) no-repeat top right; } #fold_box { position: absolute; right: 100px; top: 0; width: 146px; height: 54px; } #fold h2 { margin: 0; width: 146px; height: 54px; padding-top: 18px; line-height: 36px; text-indent: 50px; font-size: 16px; color: #fff; background: url(http://www.miaov.com/2013/img/topMenu/topMenu.png) no-repeat; position: relative; z-index: 2; font-family: arial; -ms-transform: translateZ(1px); -moz-transform: translateZ(1px); -webkit-transform: translateZ(1px); -o-transform: translateZ(1px); transform: translateZ(1px); } #fold_list { list-style: none; margin: 0; padding: 0; } .fold_pager { width: 146px; height: 30px; transform-origin: center top; } #fold_list a { display: inline-block; background-color: rgb(223, 223, 223); width: 146px; height: 29px; margin-bottom: 1px; line-height: 29px; color: #d16c6c; text-indent: 16px; font-size: 13px; text-decoration: none; z-index: 3; font-family: arial; -ms-transition: 0.6s; -moz-transition: 0.6s; -webkit-transition: 0.6s; -o-transition: 0.6s; transition: 0.6s; } #fold_list a:hover { background-color: #f69 !important; color: #fff; text-indent: 20px; font-size: 14px; box-shadow: 1px 1px 3px 2px #dfdfdf; }