3D滾動下拉菜單-簡直不要太任性

看到一個很棒的菜單效果,分享一下
原文 3D滾動下拉菜單-簡直不要太任性javascript

預覽(先看看最終效果)

http://runjs.cn/detail/re75abbwcss

簡介(由來)

最初看到這個是在14年5月,猛戳這裏:妙味官網,以爲很是炫。想要作出來,因此就開始學習web。html

那時候是作c/s的,也由於這個走上了b/s之路, 如今先後臺都要寫了。java

前幾天又來試試,發現本身能大概實現了,好屌。jquery

由於平時主要是實現功能,因此可能一些代碼習慣,實現方式不太好,但願指出來。css3

前提(須要瞭解的東西)

1. css3基礎

我也是一個菜鳥,會的很少( ̄∇ ̄),就不在這裏show無知了,主要涉及到:transform,transform-style(IE不支持?)web

能夠參見:Transform-style和Perspective屬性算法

2. 瞭解緩動

你們玩一玩這個菜單,會看到它不是勻速展開的,而是在展開動做的末尾「抖」一下學習

這個涉及到算法...我我的僅做了解(就是隻知道這個東西,怎麼實現不知道)動畫

各類緩動效果和更詳細的說明:JavaScript Tween算法及緩動效果

3. 利用jquery來實現緩動

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);
    }
});

clipboard.png

哈哈,看到這個你們就有思路了吧:

根據要改變的樣式定義一個對象,利用animate改變這個對象,監聽step和complete事件來拼接新的樣式賦值給你要執行動畫的元素!

具體實現(最終代碼)

在妙味官網上面看了好久都不知道從何看起,把這個作出來以後看到博友 呂大豹 將妙味的代碼扒出來了,艹,仍是沒看懂。

如下是3D下拉菜單的代碼:

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;
}
相關文章
相關標籤/搜索