平滑滚动,跨浏览器,无jQuery

时间:2018-09-09 18:28:32

标签: javascript jquery html css

在下面,您将找到我为单击本地链接时平滑滚动创建的脚本。它是通过transform完成的(没有 jQuery )。可以看到,我已经使用内联CSS 外部样式表来实现了它。我建议使用内联版本,因为可能很难猜测相关样式表的索引。

但是,问题是滚动条的实际移动发生在应用转换之后。因此,如果在滚动过渡完成之前单击链接,则代码将无法正常工作。

对此有什么想法吗?


编辑:

我知道那里有jQuery solutionsthird party polyfill libraries。但是,我的目标是用普通的JavaScript重新创建 jQuery 功能。


我的脚本:

// Get style rule's declaration block
function getStyleDeclaration(styleSheet, selectorText) {
  const rules = styleSheet.cssRules;
  return Array.from(rules).find(r => r.selectorText === selectorText).style;
  // for (let i = 0; i < rules.length; i += 1) {
  //   if (rules[i].selectorText === selectorText) return rules[i].style;
  // }
}

// Get specific style sheet, based on its title
// Many style sheets do not have a title however
// Which is main reason it is preferred to work with
// inline styles instead
function getStyleSheet(title) {
  const styleSheets = document.styleSheets;
  return Array.from(styleSheets).find(s => s.title === title);
  // for (let i = 0; i < styleSheets.length; i += 1) {
  //   if (styleSheets[i].title === title) return styleSheets[i];
  // }
}

function scrollToElement_ExternalStyleSheet(anchor, target) {
  anchor.addEventListener("click", e => {
    e.preventDefault();

    const time = 1000;
    // Distance from viewport to topof target
    const distance = -target.getBoundingClientRect().top;

    // Modify external style sheet
    const transStyle = getStyleDeclaration(document.styleSheets[1], ".trans");
    transStyle.transform = "translate(0, " + distance + "px)";
    transStyle.transition = "transform " + time + "ms ease";

    const root = document.documentElement; // <html> element
    root.classList.add("trans");

    window.setTimeout(() => {
      root.classList.remove("trans");
      root.scrollTo(0, -distance + window.pageYOffset);
    }, time);
  });
}

function scrollToElement_InlineStyle(anchor, target) {
  const root = document.documentElement;
  anchor.addEventListener('click', e => {
    e.preventDefault();

    const time = 900;
    const distance = -target.getBoundingClientRect().top;

    root.style.transform = 'translate(0, ' + distance + 'px)';
    root.style.transition = 'transform ' + time + 'ms ease';

    window.setTimeout(() => {
      root.scrollTo(0, -distance + window.pageYOffset);
      root.style.transform = null; // Revert to default
      root.style.transition = null;
    }, time);
  });
}

function applySmoothScroll() {
  const anchors = document.querySelectorAll("a");
  const localAnchors = Array.from(anchors).filter(
    a => a.getAttribute("href").indexOf("#") != -1
  );
  localAnchors.forEach(a => {
    const targetString = a.getAttribute("href");
    const target = document.querySelector(targetString);
    // scrollToElement_ExternalStyleSheet(a, target);
    scrollToElement_InlineStyle(a, target);
  });
}

applySmoothScroll();
.box {
  padding-bottom: 300px;
  padding-top: 0.5rem;
  background-color: orange;
  text-align: center;
  font-size: 200%;
}

.box:nth-child(even) {
  background-color: lightblue;
  color: white;
}

a {
  color: black;
}

body {
  margin: 0;
}

.trans {
  transform: translate(0, -100px);
  transition: transform 900ms ease;
}
<div id="s0" class="box"><a href="#s1">Click Me!</a></div>
<div id="s1" class="box"><a href="#s2">Click Me!</a></div>
<div id="s2" class="box"><a href="#s0">Click Me!</a></div>

0 个答案:

没有答案