我有一个页面,其中一个滚动条包含从数据库动态生成的带有div的表行。每个表行就像一个链接,有点像你在视频播放器旁边看到的YouTube播放列表。

当用户访问页面时,他们所在的选项应该会转到滚动div的顶部。这个功能正在工作。问题是,这有点太过分了。比如他们的选项高了10像素。因此,页面被访问,url被用来识别选择了哪个选项,然后将该选项滚动到滚动div的顶部。注意:这不是窗口的滚动条,这是一个带有滚动条的div。

我正在使用这段代码,使它移动选中的选项到div的顶部:

var pathArray = window.location.pathname.split( '/' );

var el = document.getElementById(pathArray[5]);

el.scrollIntoView(true);

它将它移动到div的顶部,但大约10个像素太高了。 有人知道怎么解决吗?


当前回答

也许这有点笨拙,但到目前为止还不错。我在angular 9工作。

文件.ts

scroll(el: HTMLElement) {
  el.scrollIntoView({ block: 'start',  behavior: 'smooth' });   
}

. html文件

<button (click)="scroll(target)"></button>
<div  #target style="margin-top:-50px;padding-top: 50px;" ></div>

我用边距和填充顶部调整偏移量。

问候!

其他回答

这适用于我的Chrome浏览器(平滑滚动,没有计时黑客)

它只是移动元素,开始滚动,然后再移动回来。

如果元素已经在屏幕上,则不会出现可见的“弹出”。

pos = targetEle.style.position;
top = targetEle.style.top;
targetEle.style.position = 'relative';
targetEle.style.top = '-20px';
targetEle.scrollIntoView({behavior: 'smooth', block: 'start'});
targetEle.style.top = top;
targetEle.style.position = pos;

找到了一个变通的解决方案。假设你想滚动到一个div,比如这里的Element,你想在它上面有一个20px的间距。 在上面设置一个已创建的div的ref:

<div ref={yourRef} style={{position: 'relative', bottom: 20}}/> < / >元素

这样做将创建您想要的间距。

如果你有一个标题,在标题后面创建一个空的div,并给它分配一个与标题高度相等的高度并引用它。

我试着使用上面的一些答案,但滚动不起作用。经过一番研究,我注意到滚动位置实际上非常奇怪(甚至是负值),这是由Angular在路由器出口中渲染页面的方式引起的。

我的解决方案是从页面顶部开始计算元素的滚动位置。我在模板的开头放置了一个id为start-of-page的元素,通过减去目标片段位置来获得滚动量。

 ngAfterViewInit(): void {
    this.route.fragment.subscribe(fragment => {
      try {
        // @ts-ignore
        // document.querySelector('#hero').scrollIntoView({behavior:smooth, block: "start", inline: "start"});
        // @ts-ignore
        // document.querySelector('#' + fragment).scrollIntoView({behavior:smooth, block: "start", inline: "start"});
        this._scrollTo('#' + fragment,0);
      } catch (e) { };
    });
  }

private _scrollTo(selector: any, yOffset = 0){
    const base = document.querySelector('#start-of-page');
    const el = document.querySelector(selector);
    // @ts-ignore
    const y = el.getBoundingClientRect().top - base.getBoundingClientRect().top; 
    window.scrollTo({top: y, behavior: 'smooth'});
  }

把我的解决方案留在这里,以防有人想达到和我一样的目标。

在我的例子中,错误或通知出现在提交后的页面顶部。(游戏邦注:对于几页滚动来说,页面有点长,在手机上则更长。)

我使用下面的代码片段将错误或通知滚动到视图中。

requestAnimationFrame (() = > errorOrNotification.scrollIntoView ({ Block: 'end', behavior: 'smooth' }) );

Block: 'end'是窍门。根据文档::它反映了alignToTop: false场景。为了融合平滑滚动,我添加了相同的替换。

从本质上讲,它将尝试将元素的底部与可滚动祖先(在我的例子中是窗口)的可见区域的底部对齐。

UPD:我已经创建了一个npm包,它比下面的解决方案更好,更容易使用。

我的smoothScroll函数

我采用了Steve Banton的出色解决方案,并编写了一个函数,使其使用起来更方便。使用window.scroll()甚至window.scrollBy()会更容易,因为我以前尝试过,但这两个有一些问题:

一切都变成垃圾后,使用他们与平稳的行为。 你无论如何都不能阻止他们,必须等到卷轴的结尾。 希望我的函数对你们有用。此外,还有一个轻量级的填充程序,可以在Safari甚至IE中运行。

下面是代码

照搬就行,想怎么搞就怎么搞。

import smoothscroll from 'smoothscroll-polyfill';

smoothscroll.polyfill();

const prepareSmoothScroll = linkEl => {
  const EXTRA_OFFSET = 0;

  const destinationEl = document.getElementById(linkEl.dataset.smoothScrollTo);
  const blockOption = linkEl.dataset.smoothScrollBlock || 'start';

  if ((blockOption === 'start' || blockOption === 'end') && EXTRA_OFFSET) {
    const anchorEl = document.createElement('div');

    destinationEl.setAttribute('style', 'position: relative;');
    anchorEl.setAttribute('style', `position: absolute; top: -${EXTRA_OFFSET}px; left: 0;`);

    destinationEl.appendChild(anchorEl);

    linkEl.addEventListener('click', () => {
      anchorEl.scrollIntoView({
        block: blockOption,
        behavior: 'smooth',
      });
    });
  }

  if (blockOption === 'center' || !EXTRA_OFFSET) {
    linkEl.addEventListener('click', () => {
      destinationEl.scrollIntoView({
        block: blockOption,
        behavior: 'smooth',
      });
    });
  }
};

export const activateSmoothScroll = () => {
  const linkEls = [...document.querySelectorAll('[data-smooth-scroll-to]')];

  linkEls.forEach(linkEl => prepareSmoothScroll(linkEl));
};

要创建一个link元素,只需添加以下data属性:

data-smooth-scroll-to="element-id"

还可以将另一个属性设置为加法

data-smooth-scroll-block="center"

它表示scrollIntoView()函数的块选项。默认为start。在MDN上阅读更多。

最后

根据您的需要调整平滑滚动功能。

例如,如果你有一些固定的标题(或者我用单词masthead来称呼它),你可以这样做:

const mastheadEl = document.querySelector(someMastheadSelector);

// and add it's height to the EXTRA_OFFSET variable

const EXTRA_OFFSET = mastheadEl.offsetHeight - 3;

如果你没有这样的情况,那就删除它,为什么不:-D。