使用纯JS滚动到使用div(不是窗口)的位置 [英] Scroll to position WITHIN a div (not window) using pure JS

查看:96
本文介绍了使用纯JS滚动到使用div(不是窗口)的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PURE JS只能请 - 没有JQUERY

PURE JS ONLY PLEASE - NO JQUERY

我有一个带溢出滚动的div,窗口(html / body)永远不会溢出。

I have a div with overflow scroll, the window (html/body) never overflows itself.

我有一个锚链接列表,想要点击它们时滚动到一个位置。

I have a list of anchor links and want to scroll to a position when they're clicked.

基本上只是寻找锚点滚动来自div,而不是窗口。

Basically just looking for anchor scrolling from within a div, not window.

window.scrollTo等不起作用,因为窗口永远不会溢出。

window.scrollTo etc. don't work as the window never actually overflows.

简单测试用例 http://codepen.io/mildrenben/pen/RPyzqm

JADE

nav
  a(data-goto="#1") 1
  a(data-goto="#2") 2
  a(data-goto="#3") 3
  a(data-goto="#4") 4
  a(data-goto="#5") 5
  a(data-goto="#6") 6

main
  p(data-id="1") 1
  p(data-id="2") 2
  p(data-id="3") 3
  p(data-id="4") 4
  p(data-id="5") 5
  p(data-id="6") 6

SCSS

html, body {
  width: 100%;
  height: 100%;
  max-height: 100%;
}

main {
  height: 100%;
  max-height: 100%;
  overflow: scroll;
  width: 500px;
}

nav {
  background: red;
  color: white;
  position: fixed;
  width: 50%;
  left: 50%;
}

a {
  color: white;
  cursor: pointer;
  display: block;
  padding: 10px 20px;
  &:hover {
    background: lighten(red, 20%);
  }
}

p {
  width: 400px;
  height: 400px;
  border: solid 2px green;
  padding: 30px;
}

JS

var links = document.querySelectorAll('a'),
    paras = document.querySelectorAll('p'),
    main  = document.querySelector('main');

for (var i = 0; i < links.length; i++) {
  links[i].addEventListener('click', function(){
    var linkID = this.getAttribute('data-goto').slice(1);
    for (var j = 0; j < links.length; j++) {
      if(linkID === paras[j].getAttribute('data-id')) {
         window.scrollTo(0, paras[j].offsetTop); 
      }
    }
  })
}

只有PURE JS请 - 没有JQUERY

PURE JS ONLY PLEASE - NO JQUERY

推荐答案

你想要的是设置 < main> 元素上的scrollTop 属性。

What you want is to set the scrollTop property on the <main> element.

var nav = document.querySelector('nav'),
    main  = document.querySelector('main');

  nav.addEventListener('click', function(event){
    var linkID,
      scrollTarget;
    if (event.target.tagName.toUpperCase() === "A") {
      linkID = event.target.dataset.goto.slice(1);
      scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
      main.scrollTop = scrollTarget.offsetTop;
    }
  });

你会注意到我做了其他几件不同的事情:

You'll notice a couple of other things I did different:


  • 我用事件委托因此我只需将一个事件附加到 nav 元素,这将更有效地处理任何链接上的点击。

  • 同样,我没有循环遍历所有 p 元素,而是选择了我想要的属性选择器

  • I used event delegation so I only had to attach one event to the nav element which will more efficiently handle clicks on any of the links.
  • Likewise, instead of looping through all the p elements, I selected the one I wanted using an attribute selector

这不仅更高效,可扩展,而且还可以生成更短,更易于维护的代码。

This is not only more efficient and scalable, it also produces shorter, easier to maintain code.

这段代码只会跳转到元素,对于动画卷轴,你需要编写一个函数逐步更新 scrollTop 之后使用<$ c的小延迟$ c> setTimeout

This code will just jump to the element, for an animated scroll, you would need to write a function that incrementally updates scrollTop after small delays using setTimeout.

var nav = document.querySelector('nav'),
    main  = document.querySelector('main'),
    scrollElementTo = (function () {
      var timerId;
      return function (scrollWithin, scrollTo, pixelsPerSecond) {
        scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
        var pixelsPerTick = pixelsPerSecond / 100,
          destY = scrollTo.offsetTop,
          direction = scrollWithin.scrollTop < destY ? 1 : -1,
          doTick = function () {
            var distLeft = Math.abs(scrollWithin.scrollTop - destY),
              moveBy = Math.min(pixelsPerTick, distLeft);
            scrollWithin.scrollTop += moveBy * direction;
            if (distLeft > 0) {
              timerId = setTimeout(doTick, 10);
            }
          };
        clearTimeout(timerId);
        doTick();
      };
    }());

nav.addEventListener('click', function(event) {
  var linkID,
    scrollTarget;
  if (event.target.tagName.toUpperCase() === "A") {
    linkID = event.target.dataset.goto.slice(1);
    scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
    scrollElementTo(main, scrollTarget, 500);
  }
});

您可能遇到的另一个问题是,如果 a 元素包含子元素并且单击子元素,它将是事件的目标而不是 a 标记本身。您可以使用我写的 getParentAnchor 函数来解决这个问题这里

Another problem you might have with the event delegation is that if the a elements contain child elements and a child element is clicked on, it will be the target of the event instead of the a tag itself. You can work around that with something like the getParentAnchor function I wrote here.

这篇关于使用纯JS滚动到使用div(不是窗口)的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆