文章出處

昨晚想仿造下音悅臺首頁“返回頂部”的小超人效果,覺得這東西的實現很簡單,應該不會費時超過一個鐘。結果擼代碼的過程發現存在很多意想不到的問題。

先發個圖:

有興趣的朋友可以去音悅臺點一下這個小超人圖標試一試,默認是隱藏的,滾動條下拉一小段距離后會從下面飛上來懸停在右下角,點擊的時候不但瀏覽器滾動條會返回頂端,小超人也會往上飛到頂部消失掉。

不過我印象中,以前若鼠標移到圖標上,小超人會變成一個動態(小超人的披風會擺動)的gif圖,不過現在取消了這效果,可能是因為gif畢竟不是png,多少帶有些鋸齒影響了美觀。

繼續到咱“理思路”時間,我們要實現的效果如下圖所示,即開始和結束狀態,懸浮圖標都是位于窗口下方看不到的地方,當瀏覽器滾動條被拉動一小段距離(假設250px)后,圖標從下向上移動到某個看得到的位置(假設距離瀏覽器底部50px)并一直懸浮于此,只有點擊后觸發瀏覽器滾動條置頂,并讓自己垂直飛到頂端消失(消失后重回底部看不到的位置):

 

先寫下原型:

<head>
<style>
.long{width:100%; height:1000px;}
.long2{width:100%; height:900px;background-color:yellow;}
a{display:block; position:fixed; z-index:50px; right:10px; width:30px; height:30px; background-color:green;}
</style>
<script src="jq.js"></script>
<meta charset="utf-8">
<title>無標題文檔</title>
</head>

<body>
  <a href="javascript:void(0);"></a><!--返回頂部的懸浮圖標-->
  <div class="long">
  占位符啊占位符
  </div>
  <div class="long2">
  依舊是占位符啊占位符。。。
  </div>

</body>
View Code

初步腳本:

    var $toTop = $("a"), $win=$(window);
    var a_h = $toTop.height();
    var a_btm = 150;   //懸浮距離
    var act_h = 250;   //觸發圖標出現的下拉框下拉距離
    $toTop.css("bottom",-a_h); //默認圖標位于看不到的窗口下方
    
    var f1 = function(){
        $toTop.css({"bottom" : -a_h});
    }
    var f2 = function(){
        $toTop.animate({"bottom":a_btm},400,function(){
            $toTop.css({"bottom":a_btm});  //圖標從下飛上來后固定住位置不變
            if($win.scrollTop()<act_h) f1();  //處理“圖標飛動過程用戶又將下拉框拉到上面”的事件
        });
    }

    ////滾動條滾動事件
    scrollFun = function(){
        if($win.scrollTop()<act_h) f1();
        else f2();
    }
    
    $win.on("scroll resize",scrollFun);
    $toTop.click(function(){
            $toTop.stop().animate({bottom:$win.height()},500);  //圖標飛到上面消失掉
            $('body,html').stop().animate({scrollTop:0},500);   //下拉框返回頂部
    })

其中f1對應 “初始化時,圖標位于下面看不到的狀態”;

f2對應 “下拉框拖動到某個距離(本例為250px)時,圖標從下面飛上來的狀態,并一直處于懸浮位置的狀態”;

注意這里f2使用了animate的callback,要求圖標飛上來后才修改其bottom值,避免覆蓋了動畫效果。

另外這里需要考慮避免f2重復執行的情況,畢竟拖動下拉框的時候是不斷地在觸發窗體scroll事件,會導致f2的動畫不斷進入圖標的動作隊列。當然有同學會考慮用stop()解決,但那樣會導致卡頓的情況,無法實現音悅臺那樣流暢的效果。

所以咱們只要讓f2只執行一次即可,當下拉框拉回頂部的時候則重置其可執行狀態,可以利用標志位實現,腳本修改為:

    var flag = !0;   //新增標志位
    var $toTop = $("a"), $win=$(window);
    var a_h = $toTop.height();
    var a_btm = 150; 
    var act_h = 250;  
    $toTop.css("bottom",-a_h); 
    
    var f1 = function(){
        $toTop.css({"bottom" : -a_h});
        flag = !0;   //重置標志位
    }
    var f2 = function(){
        flag = !1;  //修改標志位,避免f2重復執行
        $toTop.animate({"bottom":a_btm},400,function(){
            $toTop.css({"bottom":a_btm});
            if($win.scrollTop()<act_h) f1();
        });
    }

    ////滾動條滾動事件
    scrollFun = function(){
        if($win.scrollTop()<act_h) f1();
        else if(flag) f2();   //標志位為true才可執行
    }
    
    $win.on("scroll resize",scrollFun);
    $toTop.click(function(){
            $toTop.stop().animate({bottom:$win.height()},500);  
            $('body,html').stop().animate({scrollTop:0},500);  
    })

可見這里定義了個標志位flag,初始化狀態為true,且只有true的情況下f2才能執行,但f2執行時也順便把flag改為fail狀態(f1執行時會重置為true)。

另外這段代碼依舊有問題,因為當用戶點擊圖標之后,觸發下拉框滾到頂部的過程中,也在不斷地觸發scrollFun事件,會導致圖標還沒來得及飛到上面消失掉時,就觸發了f1,從而導致圖標只飛了一小段距離就消失不見。

解決方法其實很簡單,在用戶點擊圖標時,通過.off()解除圖標對scrollFun事件的綁定即可,然后在圖標飛到上方消失了的動畫完成后,再重新綁定即可。最終代碼如下

    var flag = !0;
    var $toTop = $("a"), $win=$(window);
    var a_h = $toTop.height();
    var a_btm = 150;   
    var act_h = 250; 
    $toTop.css("bottom",-a_h); 
    
    var f1 = function(){
        $toTop.css({"bottom" : -a_h});
        flag = !0;
    }
    var f2 = function(){
        $win.off("scroll resize",scrollFun);
        $toTop.animate({"bottom":a_btm},400,function(){
            flag = !1;
            $toTop.css({"bottom":a_btm});
            $win.on("scroll resize",scrollFun);
            if($win.scrollTop()<act_h) f1();
        });
    }

    ////滾動條滾動事件
    scrollFun = function(){
        if($win.scrollTop()<act_h) f1();
        else if(flag) f2();
    }
    
    $win.on("scroll resize",scrollFun);
    $toTop.click(function(){
            $win.off("scroll resize",scrollFun);  //解綁scrollFun
            $toTop.stop().animate({bottom:$win.height()},500,function(){
                $win.on("scroll resize",scrollFun);  //重綁scrollFun
            });
            $('body,html').stop().animate({scrollTop:0},500);
    })


最后弱弱地說下,鑒于蘋果移動設備(ios5及更舊版本)對fixed的支持不理想,如果是做wap站點則建議將定位更換為absolute并通過修改top值來實現圖標動畫效果,或者直接使用iscroll.js來實現。

共勉~


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()