簡體   English   中英

JavaScript setTimeout無法正常工作,平滑滾動

[英]Javascript setTimeout not working properly, smooth scroll

我制作了以下凌亂的javascript,可以使div上的頁面滾動128px。

該腳本將頁面滾動到正確的位置,但不流暢。

這是因為我無法使函數setTimeout正常工作。

function pageScroll()
{   
    var from_top=$("#body_box_title_skills").offset().top;  

    scroll_speed = 15;
    goto_px = from_top - 128;

    times_scroll = goto_px / scroll_speed; 
    times_scroll = times_scroll.toString();

    times_scroll_array = times_scroll.split(".");
    times_scroll_array[1] = "0."+times_scroll_array[1];

    px_scroll_extra = times_scroll_array[1] * scroll_speed;

    scrollto_px = 0;

    while (times_scroll_array[0] >= 1)
    {
        scrollto_px = scrollto_px + scroll_speed;
        setTimeout(function(){window.scrollTo(0,scrollto_px)}, 1000);
        times_scroll_array[0]--;
    }
    scrollto_px = scrollto_px + px_scroll_extra;
    window.scrollTo(0,scrollto_px);

}

您的問題是您要關閉setTimeout的相同變量scrollto_px setTimeout函數實際運行時, scrollto_px的值與循環結束時的值相同,因此您只需立即滾動到最后一個值即可。 您需要復制到setTimeout可以關閉的新變量。

第二個問題是您要設置一個幾乎都在同一時間觸發的超時。 您需要鏈接超時,以便第一次超時發生在1000秒之后,而下一次超時發生在1000秒之后。 請注意, setTimeout與其他語言中的sleep不同。 它不會暫停執行。

您的第三個問題是您有以下幾行:

scrollto_px = scrollto_px + px_scroll_extra;
window.scrollTo(0,scrollto_px);

在您的while循環之后,它將自動跳到最后。

這是解決您遇到的問題的一種方法。 我刪除了while循環,並添加了一個在超時后將再次調用自身的函數:

function doScroll() {
    if (times_scroll_array[0] >= 1) {
        scrollto_px = scrollto_px + scroll_speed;
        console.log(scrollto_px);
        window.scrollTo(0, scrollto_px);
        times_scroll_array[0]--;
        setTimeout(doScroll, 100);
    } else {
        scrollto_px = scrollto_px + px_scroll_extra;
        window.scrollTo(0, scrollto_px);
    }
}
doScroll();

您可以看到它在這里運行(我更改了時間,因為步驟之間的1秒鍾確實很慢-但您可以根據需要進行調整): http : //jsfiddle.net/KqRwx/

問題在於,當您運行那個函數時,整個函數會在觸發任何超時之前全部運行。 你真正想要的是這樣的東西

function pageScroll(goto_px) {   
    var current_scroll = ( (window.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0) );
    var scroll_speed = 15;
    // if we are less then 15 px from the destination, scroll whatever is left to go
    if ( Math.abs(goto_px - current_scroll) <= scroll_speed) {
        window.scrollTo(0, goto_px);
    } else {
        // scroll 15 pixels in the direction where the destination is
        window.scrollTo(0, current_scroll + ((current_scroll < goto_px ? 1 : -1) * scroll_speed) );
        window.setTimeout(function(){pageScroll(goto_px)}, 1000);
    }
}


pageScroll( $("#body_box_title_skills").offset().top - 128 );

基本上,用目標調用該函數,該函數計算窗口的當前位置,並向目標滾動一次,並創建一個超時本身。 但是,此功能絕不是完美的,因為您可以通過沿相反方向調用滾動輕松地獲得無限循環,在這種情況下,您只需向后滾動並無限滾動至第四個。 應該采取其他步驟以確保在任何時候僅運行一個實例。

此外,在平滑滾動的中間手動滾動頁面將導致頁面繼續滾動直到到達目標為止,並且由於window.scrollTo觸發,監聽滾動事件以取消超時似乎也不可行。它。 一種想法是跟蹤當前滾動並取消超時(如果其意外跳出)。

補充說明:我不確定requestAnimationFrame是否適用於此,但是要獲得一致,盡可能平滑的動畫,通常這就是您要使用的。 可能值得一讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM