Próbuję zrobić to tak, aby po kliknięciu przycisku przewijał się (płynnie) w dół do określonego elementu div na stronie.
Potrzebuję tego, że jeśli klikniesz przycisk, płynnie przewinie się do „sekundy” div.
.first {
width: 100%;
height: 1000px;
background: #ccc;
}
.second {
width: 100%;
height: 1000px;
background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>
javascript
jquery
Erik Fischer
źródło
źródło
Odpowiedzi:
zrobić:
$("button").click(function() { $('html,body').animate({ scrollTop: $(".second").offset().top}, 'slow'); });
Zaktualizowano Jsfiddle
źródło
Istnieje wiele przykładów płynnego przewijania przy użyciu bibliotek JS, takich jak jQuery, Mootools, Prototype itp.
Poniższy przykład dotyczy czystego JavaScript. Jeśli nie masz jQuery / Mootools / Prototype na stronie lub nie chcesz przeładowywać strony ciężkimi bibliotekami JS, przykład będzie pomocny.
http://jsfiddle.net/rjSfP/
Część HTML:
<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div> <div class="second" id="second">Hi</div>
Część CSS:
.first { width: 100%; height: 1000px; background: #ccc; } .second { width: 100%; height: 1000px; background: #999; }
Część JS:
window.smoothScroll = function(target) { var scrollContainer = target; do { //find scroll container scrollContainer = scrollContainer.parentNode; if (!scrollContainer) return; scrollContainer.scrollTop += 1; } while (scrollContainer.scrollTop == 0); var targetY = 0; do { //find the top of target relatively to the container if (target == scrollContainer) break; targetY += target.offsetTop; } while (target = target.offsetParent); scroll = function(c, a, b, i) { i++; if (i > 30) return; c.scrollTop = a + (b - a) / 30 * i; setTimeout(function(){ scroll(c, a, b, i); }, 20); } // start scrolling scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0); }
źródło
Bawiłem się trochę odpowiedzią nico i poczułem się nerwowo. Zrobiłem trochę badania i odkryłem,
window.requestAnimationFrame
która jest funkcją, która jest wywoływana w każdym cyklu ponownego malowania. Pozwala to na bardziej przejrzystą animację. Nadal próbuję doskonalić dobre wartości domyślne dla rozmiaru kroku, ale dla mojego przykładu rzeczy wyglądają całkiem dobrze przy użyciu tej implementacji.var smoothScroll = function(elementId) { var MIN_PIXELS_PER_STEP = 16; var MAX_SCROLL_STEPS = 30; var target = document.getElementById(elementId); var scrollContainer = target; do { scrollContainer = scrollContainer.parentNode; if (!scrollContainer) return; scrollContainer.scrollTop += 1; } while (scrollContainer.scrollTop == 0); var targetY = 0; do { if (target == scrollContainer) break; targetY += target.offsetTop; } while (target = target.offsetParent); var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP, (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS); var stepFunc = function() { scrollContainer.scrollTop = Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop); if (scrollContainer.scrollTop >= targetY) { return; } window.requestAnimationFrame(stepFunc); }; window.requestAnimationFrame(stepFunc); }
źródło
scrollContainer = scrollContainer.parentNode
scrollContainer ma wartość null. Prawdopodobnie oznacza to, żeelementId
wywołując tę funkcję, nie przekazujesz poprawnego wyniku. Możliwe jest również, że uruchamiasz ten skrypt na stronie, na której ten elementId nie istnieje.elementId
było źle, otrzymałbym ten sam błąd w przypadku przykładu @nico, ale w tym przypadku przewijanie działa, ale nie płynnie.requestAnimationFrame
zamiastsetTimeout
to najlepszy sposób.setTimeout
nie powinny być używane do animacji.Co jeśli używasz funkcji scrollIntoView?
var elmntToView = document.getElementById("sectionId"); elmntToView.scrollIntoView();
Ma też {zachowanie: "gładkie"} ...;) https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
źródło
Wziąłem wersję Neda Rocksona i dostosowałem ją tak, aby umożliwiała również przewijanie w górę.
var smoothScroll = function(elementId) { var MIN_PIXELS_PER_STEP = 16; var MAX_SCROLL_STEPS = 30; var target = document.getElementById(elementId); var scrollContainer = target; do { scrollContainer = scrollContainer.parentNode; if (!scrollContainer) return; scrollContainer.scrollTop += 1; } while (scrollContainer.scrollTop === 0); var targetY = 0; do { if (target === scrollContainer) break; targetY += target.offsetTop; } while (target = target.offsetParent); var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP, Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS); var isUp = targetY < scrollContainer.scrollTop; var stepFunc = function() { if (isUp) { scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep); if (scrollContainer.scrollTop <= targetY) { return; } } else { scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep); if (scrollContainer.scrollTop >= targetY) { return; } } window.requestAnimationFrame(stepFunc); }; window.requestAnimationFrame(stepFunc); };
źródło
Możesz użyć podstawowego CSS, aby uzyskać płynne przewijanie
źródło
Ned Rockson w zasadzie odpowiada na to pytanie. Jednak w jego rozwiązaniu jest fatalna wada. Gdy docelowy element znajduje się bliżej dołu strony niż viewport-height, funkcja nie osiąga instrukcji wyjścia i zatrzymuje użytkownika na dole strony. Można to po prostu rozwiązać, ograniczając liczbę iteracji.
var smoothScroll = function(elementId) { var MIN_PIXELS_PER_STEP = 16; var MAX_SCROLL_STEPS = 30; var target = document.getElementById(elementId); var scrollContainer = target; do { scrollContainer = scrollContainer.parentNode; if (!scrollContainer) return; scrollContainer.scrollTop += 1; } while (scrollContainer.scrollTop == 0); var targetY = 0; do { if (target == scrollContainer) break; targetY += target.offsetTop; } while (target = target.offsetParent); var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP, (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS); var iterations = 0; var stepFunc = function() { if(iterations > MAX_SCROLL_STEPS){ return; } scrollContainer.scrollTop = Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop); if (scrollContainer.scrollTop >= targetY) { return; } window.requestAnimationFrame(stepFunc); }; window.requestAnimationFrame(stepFunc); }
źródło