Медленно прокрутите страницу вниз без интенсивного использования процессора или медленной прокрутки
Я хочу сделать прокрутку страницы вниз медленно и плавно. Ну, скорость вообще-то должна регулироваться. Пользователь также должен иметь возможность прокручивать вручную, пока скрипт прокручивается вниз. Сначала я попробовал это:
var autoScrollDelay = 1
var autoScrollSpeed = 1
var autoScrollTimer
function setAutoScroll(newValue) {
autoScrollSpeed = newValue ? newValue : autoScrollSpeed
if (autoScrollTimer) {
clearInterval(autoScrollTimer)
}
if (autoScrollDelay) {
autoScrollTimer = setInterval(function(){
window.scrollBy(0,autoScrollSpeed)
},autoScrollDelay)
}
}
setAutoScroll(1) // higher number = faster scrolling
но это вызывало очень тяжелую загрузку процессора, и самая медленная скорость была слишком быстрой. И в дополнение к этому ручная прокрутка не работала должным образом во время работы кода.
затем я попробовал:
var autoScrollDelay = 1
var autoScrollSpeed = 1
var autoScrollTimer
function setAutoScroll(newValue) {
autoScrollDelay = newValue ? newValue : autoScrollDelay //using autoScrollDelay instead of autoScrollSpeed
if (autoScrollTimer) {
clearInterval(autoScrollTimer)
}
if (autoScrollDelay) {
autoScrollTimer = setInterval(function(){
window.scrollBy(0,autoScrollSpeed)
},autoScrollDelay)
}
}
setAutoScroll(200) // higher number scrolls slower
но скроллинг не был гладким при установке его слишком медленно (например, 200).
затем я попробовал:
$("html, body").animate({
scrollTop: $('html, body').get(0).scrollHeight,
}, 40000, "linear");
но снова загрузка процессора была неоправданно высокой, и прокрутка вверх или вниз вручную не была возможна таким образом.
есть ли лучший способ сделать это?
2 ответов
вот одна возможная реализация. Частота обновления фиксирована и соответствует fps
в коде ниже. Чтобы убедиться, что скорость постоянна, я учитываю время, прошедшее с момента предыдущего прокрутки при расчете новой позиции прокрутки. Ручная прокрутка разрешена (с полосой прокрутки, колесиком мыши или с касанием на мобильных устройствах) и учитывается при обработке scroll
, wheel
и touchmove
событий. Вы можете увидеть код на работе в этот сайт CodePen.
var fps = 100;
var speedFactor = 0.001;
var minDelta = 0.5;
var autoScrollSpeed = 10;
var autoScrollTimer, restartTimer;
var isScrolling = false;
var prevPos = 0, currentPos = 0;
var currentTime, prevTime, timeDiff;
window.addEventListener("scroll", function (e) {
// window.pageYOffset is the fallback value for IE
currentPos = window.scrollY || window.pageYOffset;
});
window.addEventListener("wheel", handleManualScroll);
window.addEventListener("touchmove", handleManualScroll);
function handleManualScroll() {
// window.pageYOffset is the fallback value for IE
currentPos = window.scrollY || window.pageYOffset;
clearInterval(autoScrollTimer);
if (restartTimer) {
clearTimeout(restartTimer);
}
restartTimer = setTimeout(() => {
prevTime = null;
setAutoScroll();
}, 50);
}
function setAutoScroll(newValue) {
if (newValue) {
autoScrollSpeed = speedFactor * newValue;
}
if (autoScrollTimer) {
clearInterval(autoScrollTimer);
}
autoScrollTimer = setInterval(function(){
currentTime = Date.now();
if (prevTime) {
if (!isScrolling) {
timeDiff = currentTime - prevTime;
currentPos += autoScrollSpeed * timeDiff;
if (Math.abs(currentPos - prevPos) >= minDelta) {
isScrolling = true;
window.scrollTo(0, currentPos);
isScrolling = false;
prevPos = currentPos;
prevTime = currentTime;
}
}
} else {
prevTime = currentTime;
}
}, 1000 / fps);
}
setAutoScroll(20);
функции в этой статье использует vanilla JS для реализации плавной прокрутки на различных скоростях. Вот демо:
document.getElementById("scrollBottomButton").onclick = function() {
var duration = document.getElementById("bottomScrollDuration").value * 1000;
scrollIt(document.querySelector("#bottom-row"), duration, "easeOutQuad");
};
document.getElementById("scrollTopButton").onclick = function() {
var duration = document.getElementById("topScrollDuration").value * 1000;
scrollIt(document.getElementById("top-row"), duration, "easeOutQuad");
};
// thanks to https://pawelgrzybek.com/page-scroll-in-vanilla-javascript/
function scrollIt(destination, duration = 200, easing = "linear", callback) {
const easings = {
linear(t) {
return t;
},
easeOutQuad(t) {
return t * (2 - t);
}
};
const start = window.pageYOffset;
const startTime = "now" in window.performance
? performance.now()
: new Date().getTime();
const documentHeight = Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.documentElement.clientHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight
);
const windowHeight =
window.innerHeight ||
document.documentElement.clientHeight ||
document.getElementsByTagName("body")[0].clientHeight;
const destinationOffset = typeof destination === "number"
? destination
: destination.offsetTop;
const destinationOffsetToScroll = Math.round(
documentHeight - destinationOffset < windowHeight
? documentHeight - windowHeight
: destinationOffset
);
if ("requestAnimationFrame" in window === false) {
window.scroll(0, destinationOffsetToScroll);
if (callback) {
callback();
}
return;
}
function scroll() {
const now = "now" in window.performance
? performance.now()
: new Date().getTime();
const time = Math.min(1, (now - startTime) / duration);
const timeFunction = easings[easing](time);
window.scroll(
0,
Math.ceil(timeFunction * (destinationOffsetToScroll - start) + start)
);
if (window.pageYOffset === destinationOffsetToScroll) {
if (callback) {
callback();
}
return;
}
requestAnimationFrame(scroll);
}
scroll();
}
// scroll testing
var middleHtml = [];
const schiller = "Nur Beharrung führt zum Ziel, Nur die Fülle führt zur Klarheit, Und im Abgrund wohnt die Wahrheit.".split(' ')
for(var i=0; i<schiller.length;i+=1){
middleHtml.push("<div class=' container row' id='scrolling'><h1 style='margin: 30rem 10rem 30rem 0;font-size: 3.5em;font-family: Helvetica, sans-serif;color: #fff;'>"+schiller[i]+"</h1></div>");
}
document.getElementById('middle').innerHTML = middleHtml.join('');
.container-fluid {
background: #e52d27;
background: -webkit-linear-gradient(to top, #b31217, #e52d27);
background: linear-gradient(to top, #b31217, #e52d27);
}
.container-fluid input, .container-fluid .btn {
border-radius: 0;
}
.btn {
background: rgba(210,200,200,0.95);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class='container-fluid'>
<div class='row' id='top-row'>
<div class='col-sm-8'>
<input class='form-control' id='bottomScrollDuration' placeholder='Enter duration in seconds (4, 25, 40, etc...)' />
</div>
<div class='col-sm-4'>
<button class='btn' id='scrollBottomButton'>Scroll to bottom</button>
</div>
</div>
<div id='middle'>
</div>
<div class='row' id='bottom-row'>
<div class='col-sm-8'>
<input class='form-control' id='topScrollDuration' placeholder='Enter duration in seconds (4, 25, 40, etc...)' />
</div>
<div class='col-sm-4'>
<button class='btn' id='scrollTopButton'>Scroll to top</button>
</div>
</div>
</div>
посмотреть Сайт CodePen Демо
обновление
вы можете попробовать это, если вы просто хотите настроить скорость и сохранить постоянное поведение прокрутки:
function pageScroll(speed) {
window.scrollBy(0,1);
scrolldelay = setTimeout(pageScroll,speed);
}
а затем вызовите функцию со скоростью вашего выбор то есть:
pageScroll(1);
Я проверил в Chrome, и это не налог моем ЦП. Процессор делает всплеск больше, когда он работает в Firefox.