Javascript - window.scroll({behavior:'smooth'})在Safari中不起作用

Sor*_* Ly 9 javascript safari

正如标题所说,它在Chrome上运行得非常好.但在Safari中,它只是将页面设置为所需的顶部和左侧位置.这是预期的行为吗?有没有办法使它很好地工作?

小智 13

IE/Edge/Safari 并不完全支持行为选项,因此您必须自己实现一些东西。我相信 jQuery 已经有了一些东西,但如果你不使用 jQuery,这里有一个纯 JavaScript 实现:

function SmoothVerticalScrolling(e, time, where) {
    var eTop = e.getBoundingClientRect().top;
    var eAmt = eTop / 100;
    var curTime = 0;
    while (curTime <= time) {
        window.setTimeout(SVS_B, curTime, eAmt, where);
        curTime += time / 100;
    }
}

function SVS_B(eAmt, where) {
    if(where == "center" || where == "")
        window.scrollBy(0, eAmt / 2);
    if (where == "top")
        window.scrollBy(0, eAmt);
}
Run Code Online (Sandbox Code Playgroud)

如果您需要水平滚动:

function SmoothHorizontalScrolling(e, time, amount, start) {
    var eAmt = amount / 100;
    var curTime = 0;
    var scrollCounter = 0;
    while (curTime <= time) {
        window.setTimeout(SHS_B, curTime, e, scrollCounter, eAmt, start);
        curTime += time / 100;
        scrollCounter++;
    }
}

function SHS_B(e, sc, eAmt, start) {
    e.scrollLeft = (eAmt * sc) + start;
}
Run Code Online (Sandbox Code Playgroud)

一个示例调用是:

SmoothVerticalScrolling(myelement, 275, "center");
Run Code Online (Sandbox Code Playgroud)

  • @George Daniel,对原生 JS 解决方案的赞扬,尽管您可以通过在代码中添加一些内联注释来改进您的答案。 (5认同)
  • 应该使用 Window.requestAnimationFrame() 而不是超时,因为性能优化并且它仅在可见时运行..等.. https://blog.teamtreehouse.com/efficient-animations-with-requestanimationframe (2认同)
  • 谢谢你@George Daniel,我做了一支小笔,试图用评论来描述你的函数的过程https://codepen.io/gfcf14/pen/qBEMWJe (2认同)

hev*_*ev1 6

对于用于平滑滚动的方法更全面的列表,请参阅我的答案在这里


window.requestAnimationFrame 可用于在精确的时间内执行平滑滚动。

为了平滑的垂直滚动,可以使用以下功能。请注意,水平滚动可以以几乎相同的方式完成。

/*
   @param time: the exact amount of time the scrolling will take (in milliseconds)
   @param pos: the y-position to scroll to (in pixels)
*/
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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

演示:

/*
   @param time: the exact amount of time the scrolling will take (in milliseconds)
   @param pos: the y-position to scroll to (in pixels)
*/
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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)
/*
   @param time: the exact amount of time the scrolling will take (in milliseconds)
   @param pos: the y-position to scroll to (in pixels)
*/
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.querySelector('button').addEventListener('click', function(e){
  scrollToSmoothly(500, 1500);
});
Run Code Online (Sandbox Code Playgroud)
html, body {
  height: 1000px;
}
Run Code Online (Sandbox Code Playgroud)

对于更复杂的情况,可以使用SmoothScroll.js 库,它处理垂直和水平平滑滚动、在其他容器元素内部滚动、不同的缓动行为、从当前位置相对滚动等等。它还支持大多数没有原生平滑滚动的浏览器。

<button>Scroll to y-position 500px in 1500ms</button>
Run Code Online (Sandbox Code Playgroud)
var easings = document.getElementById("easings");
for(var key in smoothScroll.easing){
    if(smoothScroll.easing.hasOwnProperty(key)){
        var option = document.createElement('option');
        option.text = option.value = key;
        easings.add(option);
    }
}
document.getElementById('to-bottom').addEventListener('click', function(e){
    smoothScroll({yPos: 'end', easing: easings.value, duration: 2000});
});
document.getElementById('to-top').addEventListener('click', function(e){
    smoothScroll({yPos: 'start', easing: easings.value, duration: 2000});
});
Run Code Online (Sandbox Code Playgroud)


Eug*_*nic 5

使用smootscroll polyfill(适用于所有浏览器的解决方案),易于应用且轻量级的依赖项:https : //github.com/iamdustan/smoothscroll

通过npm或yarn安装后,将其添加到主.js,.ts文件(第一个执行)

import smoothscroll from 'smoothscroll-polyfill';
// or if linting/typescript complains
import * as smoothscroll from 'smoothscroll-polyfill';

// kick off the polyfill!
smoothscroll.polyfill();
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,插入“index.js”文件中。我始终认为最好将这些配置放在“index.js”中,因为 App.js 是一个组件。 (2认同)