簡體   English   中英

平滑滾動錨鏈接沒有 jQuery

[英]Smooth scroll anchor links WITHOUT jQuery

是否可以使用平滑滾動來錨定鏈接但沒有jQuery 我正在創建一個新站點,我不想使用jQuery

擴展這個答案: https : //stackoverflow.com/a/8918062/3851798

定義好你的scrollTo 函數后,你可以在函數中傳遞你想要scrollTo 的元素。

function scrollTo(element, to, duration) {
    if (duration <= 0) return;
    var difference = to - element.scrollTop;
    var perTick = difference / duration * 10;

    setTimeout(function() {
        element.scrollTop = element.scrollTop + perTick;
        if (element.scrollTop === to) return;
        scrollTo(element, to, duration - 10);
    }, 10);
}

如果你有一個 id="footer" 的 div

<div id="footer" class="categories">…</div>

在您運行滾動的腳本中,您可以運行它,

elmnt = document.getElementById("footer");
scrollTo(document.body, elmnt.offsetTop, 600);

你有它。 沒有 jQuery 的平滑滾動。 您實際上可以在瀏覽器的控制台上使用該代碼並根據自己的喜好對其進行微調。

使用此處的函數: JavaScript animation並修改它以修改屬性(不僅僅是樣式的屬性),您可以嘗試以下操作:

演示: http : //jsfiddle.net/7TAa2/1/

就是說...

 function animate(elem, style, unit, from, to, time, prop) { if (!elem) { return; } var start = new Date().getTime(), timer = setInterval(function() { var step = Math.min(1, (new Date().getTime() - start) / time); if (prop) { elem[style] = (from + step * (to - from)) + unit; } else { elem.style[style] = (from + step * (to - from)) + unit; } if (step === 1) { clearInterval(timer); } }, 25); if (prop) { elem[style] = from + unit; } else { elem.style[style] = from + unit; } } window.onload = function() { var target = document.getElementById("div5"); animate(document.scrollingElement || document.documentElement, "scrollTop", "", 0, target.offsetTop, 2000, true); };
 div { height: 50px; }
 <div id="div1">asdf1</div> <div id="div2">asdf2</div> <div id="div3">asdf3</div> <div id="div4">asdf4</div> <div id="div5">asdf5</div> <div id="div6">asdf6</div> <div id="div7">asdf7</div> <div id="div8">asdf8</div> <div id="div9">asdf9</div> <div id="div10">asdf10</div> <div id="div10">asdf11</div> <div id="div10">asdf12</div> <div id="div10">asdf13</div> <div id="div10">asdf14</div> <div id="div10">asdf15</div> <div id="div10">asdf16</div> <div id="div10">asdf17</div> <div id="div10">asdf18</div> <div id="div10">asdf19</div> <div id="div10">asdf20</div>

實際上,有更輕量級和簡單的方法來做到這一點: https : //codepen.io/ugg0t/pen/mqBBBY

 function scrollTo(element) { window.scroll({ behavior: 'smooth', left: 0, top: element.offsetTop }); } document.getElementById("button").addEventListener('click', () => { scrollTo(document.getElementById("8")); });
 div { width: 100%; height: 200px; background-color: black; } div:nth-child(odd) { background-color: white; } button { position: absolute; left: 10px; top: 10px; }
 <div id="1"></div> <div id="2"></div> <div id="3"></div> <div id="4"></div> <div id="5"></div> <div id="6"></div> <div id="7"></div> <div id="8"></div> <div id="9"></div> <div id="10"></div> <button id="button">Button</button>

用這個:

let element = document.getElementById("box");

element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({block: "end"});
element.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"});

演示https : //jsfiddle.net/anderpo/x8ucc5ak/1/

帶有:target選擇器的 CSS3 轉換可以在沒有任何 JS hack 的情況下提供不錯的結果。 我只是在考慮是否要實現這一點,但沒有 Jquery,它確實有點混亂。 有關詳細信息,請參閱此問題

使用 polyfill 平滑滾動行為...

例子:

document.querySelectorAll('a[href^="#"]').addEventListener("click", function(event) {
  event.preventDefault();
  document.querySelector(this.getAttribute("href")).scrollIntoView({ behavior: "smooth" });
});

存儲庫: https : //github.com/iamdustan/smoothscroll

使用帶有緩動和所有瀏覽器的requestAnimationFrame Vanilla js 變體:

const requestAnimationFrame = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame;

function scrollTo(to) {
    const start = window.scrollY || window.pageYOffset
    const time = Date.now()
    const duration = Math.abs(start - to) / 3;

    (function step() {
        var dx = Math.min(1, (Date.now() - time) / duration)
        var pos = start + (to - start) * easeOutQuart(dx)

        window.scrollTo(0, pos)

        if (dx < 1) {
            requestAnimationFrame(step)
        }
    })()
}

支持任何緩動

在這里試試這個代碼:

window.scrollTo({
        top: 0,
        left: 0,
        behavior: 'smooth'
    });

這是一個很老的問題,但我認為重要的是現在 CSS 支持平滑滾動,因此不需要任何腳本:

html {
  scroll-behavior: smooth;
}

截至 2019 年,此屬性仍然不支持 Safari 或 IE/Edge,因此要獲得完整的跨瀏覽器支持,您仍然必須使用腳本。

純輕量級的JavaScript庫: 在github上順暢滾動

我目前最喜歡的滾動到庫是Zenscroll,因為它具有廣泛的功能和小尺寸(目前只有 3.17kb)。

將來,使用原生scrollIntoView功能可能更有意義,但是由於缺乏 IE 支持,現在大多數生產站點都必須對它進行 polyfill,因此我建議在所有情況下都使用 Zenscroll。

2022 年 3 月

我知道這是一個老問題,但想提出一個在現代有更簡單方法的答案。 截至今天,幾乎所有主流瀏覽器都與scroll-behavior兼容,包括最新版本的 Safari。 不過,您可能希望使用回退方法或僅使用方法 2 中描述的 javascript 方法,以便在舊瀏覽器中兼容。

方法一:HTML 和 CSS

你可以這樣做

<a href="#target" id="scroll-trigger">Click</a>
.
.
.
<h2 id="target">Target</h2>

和 CSS

html {
    scroll-behavior: smooth
} 

方法二:JavaScript

或者,如果您有一個需要 javascript、go 的獨特案例,請使用此方法進行詳細說明。

const scrollTrigger = document.getElementById('scroll-trigger');
const target = document.getElementById('target');

scrollTrigger.addEventListener('click', function (e) {
    window.scroll({
        top: target.offsetTop,
        left:0,
        behavior: 'smooth' });
}, false)

這是@Ian 的升級版

// Animated scroll with pure JS
// duration constant in ms
const animationDuration = 600;
// scrollable layout
const layout = document.querySelector('main');
const fps = 12;  // in ms per scroll step, less value - smoother animation
function scrollAnimate(elem, style, unit, from, to, time, prop) {
    if (!elem) {
        return;
    }
    var start = new Date().getTime(),
        timer = setInterval(function () {
            var step = Math.min(1, (new Date().getTime() - start) / time);
            var value =  (from + step * (to - from)) + unit;
            if (prop) {
                elem[style] = value;
            } else {
                elem.style[style] = value;
            }
            if (step === 1) {
                clearInterval(timer);
            }
        }, fps);
    if (prop) {
        elem[style] = from + unit;
    } else {
        elem.style[style] = from + unit;
    }
}

function scrollTo(hash) {
    const target = document.getElementById(hash);
    const from = window.location.hash.substring(1) || 'start';
    const offsetFrom = document.getElementById(from).offsetTop;
    const offsetTo = target.offsetTop;
    scrollAnimate(layout,
        "scrollTop", "", offsetFrom, offsetTo, animationDuration, true);
    setTimeout(function () {
      window.location.hash = hash;
    }, animationDuration+25)
};

// add scroll when click on menu items 
var menu_items = document.querySelectorAll('a.mdl-navigation__link');
menu_items.forEach(function (elem) {
    elem.addEventListener("click",
        function (e) {
            e.preventDefault();
            scrollTo(elem.getAttribute('href').substring(1));
        });
});

// scroll when open link with anchor 
window.onload = function () {
    if (window.location.hash) {
        var target = document.getElementById(window.location.hash.substring(1));
        scrollAnimate(layout, "scrollTop", "", 0, target.offsetTop, animationDuration, true);
    }
}

對於 2019 年的任何人,首先,您添加一個事件偵聽器

  document.getElementById('id').addEventListener('click', () => scrollTo())

然后你瞄准這個元素並順利地找到它

function scrollTo() {
    let target = document.getElementById('target');
    target.scrollIntoView({
        behavior: "smooth", 
        block: "end", 
        inline: "nearest"
    })
}

基於MDN 文檔的滾動選項,我們可以使用以下代碼:

element.scrollTo({
  top: 100,
  left: 100,
  behavior: 'smooth'
});

事實上, behavior鍵可以接受smoothauto變量。 首先是平滑運動,其次是單次跳躍。 ‍‍

這是純 JavaScript 的一個簡單解決方案。 它利用了 CSS 屬性scroll-behavior: smooth

function scroll_to(id) {       
    document.documentElement.style.scrollBehavior = 'smooth'
    element = document.createElement('a');
    element.setAttribute('href', id)
    element.click();
}

用法

假設我們有 10 個 div:

<div id='df7ds89' class='my_div'>ONE</div>
<div id='sdofo8f' class='my_div'>TWO</div>
<div id='34kj434' class='my_div'>THREE</div>
<div id='gbgfh98' class='my_div'>FOUR</div>
<div id='df89sdd' class='my_div'>FIVE</div>
<div id='34l3j3r' class='my_div'>SIX</div>
<div id='56j5453' class='my_div'>SEVEN</div>
<div id='75j6h4r' class='my_div'>EIGHT</div>
<div id='657kh54' class='my_div'>NINE</div>
<div id='43kjhjh' class='my_div'>TEN</div>

我們可以滾動到選擇的 ID

scroll_to('#657kh54')

您只需在單擊事件上調用此函數(例如單擊按鈕然后滾動到 div #9)。

結果

在此處輸入圖片說明

當然,它在現實生活中看起來要流暢得多。

小提琴

不幸的是,截至2019 年,IE 和 Safari 不支持 scrollBehavior = 'smooth'

在此處輸入圖片說明 MDN 網絡文檔

對於用於平滑滾動的方法更全面的列表,請參閱我的答案在這里


要在精確的時間內滾動到某個位置,可以使用window.requestAnimationFrame ,每次計算適當的當前位置。 當不支持requestAnimationFrame時,可以使用setTimeout達到類似的效果。

/*
   @param pos: the y-position to scroll to (in pixels)
   @param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
    var currentPos = window.pageYOffset;
    var start = null;
    if(time == null) time = 500;
    pos = +pos, time = +time;
    window.requestAnimationFrame(function step(currentTime) {
        start = !start ? currentTime : start;
        var progress = currentTime - start;
        if (currentPos < pos) {
            window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
        } else {
            window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
        }
        if (progress < time) {
            window.requestAnimationFrame(step);
        } else {
            window.scrollTo(0, pos);
        }
    });
}

演示:

 function scrollToSmoothly(pos, time) { var currentPos = window.pageYOffset; var start = null; if(time == null) time = 500; pos = +pos, time = +time; window.requestAnimationFrame(function step(currentTime) { start = !start ? currentTime : start; var progress = currentTime - start; if (currentPos < pos) { window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos); } else { window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time)); } if (progress < time) { window.requestAnimationFrame(step); } else { window.scrollTo(0, pos); } }); } document.getElementById("toElement").addEventListener('click', function(e) { var elem = document.querySelector("div"); scrollToSmoothly(elem.offsetTop); }); document.getElementById("toTop").addEventListener('click', function(e){ scrollToSmoothly(0, 700); });
 <button id="toElement">Scroll To Element</button> <div style="margin: 1000px 0px; text-align: center;">Div element <button id="toTop">Scroll back to top</button> </div>

對於更復雜的情況,可以使用SmoothScroll.js 庫,它處理垂直和水平平滑滾動、在其他容器元素內部滾動、不同的緩動行為、從當前位置相對滾動等等。

 document.getElementById("toElement").addEventListener('click', function(e) { smoothScroll({toElement: document.querySelector('div'), duration: 500}); }); document.getElementById("toTop").addEventListener('click', function(e){ smoothScroll({yPos: 0, duration: 700}); });
 <script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll@1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script> <button id="toElement">Scroll To Element</button> <div style="margin: 1000px 0px; text-align: center;">Div element <button id="toTop">Scroll back to top</button> </div>

或者,您可以將選項對象傳遞給window.scroll ,它滾動到特定的 x 和 y 位置,以及window.scrollBy從當前位置滾動一定量:

// Scroll to specific values
// scrollTo is the same
window.scroll({
  top: 2500, 
  left: 0, 
  behavior: 'smooth' 
});

// Scroll certain amounts from current position 
window.scrollBy({ 
  top: 100, // could be negative value
  left: 0, 
  behavior: 'smooth' 
});

演示:

 <button onClick="scrollToDiv()">Scroll To Element</button> <div style="margin: 500px 0px;">Div</div> <script> function scrollToDiv(){ var elem = document.querySelector("div"); window.scroll({ top: elem.offsetTop, left: 0, behavior: 'smooth' }); } </script>

現代瀏覽器支持scroll-behavior CSS 屬性,可用於使文檔中的滾動平滑(無需 JavaScript)。 錨標簽可用於此目的,方法是為錨標簽提供#href加上要滾動到的元素的id )。 您還可以為特定容器(如div設置scroll-behavior屬性,以使其內容平滑滾動。

 html, body{ scroll-behavior: smooth; }
 <a href="#elem">Scroll To Element</a> <div id="elem" style="margin: 500px 0px;">Div</div>

沒有jQuery

 const links = document.querySelectorAll('header nav ul a') for (const link of links) { link.onclick = function clickHandler(e) { e.preventDefault() const href = this.getAttribute('href') document.querySelector(href).scrollIntoView({ behavior: 'smooth' }) } }
 body { background-color: black; height:7000px } header { margin-top: 1.3rem; margin-bottom: 25rem; display: flex; justify-content: center; align-items: center; } nav ul { display: flex; } nav ul li { all: unset; margin: 2rem; cursor: pointer; } nav ul li a { all: unset; font: bold 1.8rem robto; color: white; letter-spacing: 1px; cursor: pointer; padding-top: 3rem; padding-bottom: 2rem; } #team, #contact, #about { background-color: #e2df0d; width: 100%; height: 35rem; display: flex; justify-content: center; align-items: center; color: black; font: bold 4rem roboto; letter-spacing: 6.2px; margin-top: 70rem; }
 <header> <!-- NavBar --> <nav> <ul> <li><a href="#team">Team</a></li> <li><a href="#contact">Contact</a></li> <li><a href="#about">About</a></li> </ul> </nav> </header> <!-- ----------- Team ----------------------- --> <div id="team"> <h2>Team</h2> </div> <!-- ----------- Contact ----------------------- --> <div id="contact"> <h2>Contact</h2> </div> <!-- ----------- About ----------------------- --> <div id="about"> <h2>About</h2> </div>

或僅使用CSS ,但尚不支持所有瀏覽器

html {scroll-behavior: smooth}

如果您想將所有深層鏈接設置為平滑滾動#您可以這樣做:

const allLinks = document.querySelectorAll('a[href^="#"]')
allLinks.forEach(link => {

  const 
    targetSelector = link.getAttribute('href'),
    target = document.querySelector(targetSelector)

  if (target) {
    link.addEventListener('click', function(e) {

    e.preventDefault()

    const top = target.offsetTop // consider decreasing your main nav's height from this number

    window.scroll({
      behavior: 'smooth',
      left: 0,
      top: top
    });

  })
}
})

一個示例代碼也要考慮您的主導航的高度(此代碼位於聲明top const 的位置):

const 
  mainHeader = document.querySelector('header#masthead'), //change to your correct main nav selector
  mainHeaderHeight = mainHeader.offsetHeight,
  // now calculate top like this:
  top = target.offsetTop - mainHeaderHeight 

這是最優雅和簡潔的解決方案。

鏈接:

<a href="#elementIDtoScrollTo"></a>

CSS:

html {
    scroll-behavior: smooth;
}

請記住為每個 HTML 元素添加一個唯一的id="elementIDtoScrollTo"

暫無
暫無

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

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