Reputation: 410
I am trying to build a scroll animation section when visitors click on the anchor. As you might notice the variable "id" will show #1, this will match the id value of the section itself. How could I add the scroll animation to this javascript?
var section = document.getElementsByTagName("section"),
nav = document.getElementById("nav-bar"),
navHeight = nav.offsetHeight,
navAnchor = nav.querySelectorAll("li a");
for (var i = 0; i < navAnchor.length; i++) {
var element = navAnchor[i];
element.addEventListener("click", function(e) {
e.preventDefault();
var el = this,
id = el.getAttribute("href");
function scrollTo(element, to, duration) {
var element = element,
to = section + id;
console.log(id);
if (duration <= 0) {
return;
}
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
consolelo
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) return;
scrollTo(element, to, duration - 10);
}, 500);
}
});
}
ul li {
list-style-type: none;
display: inline-block;
}
li a {
text-decoration: none;
display: block;
width: 120px;
padding-top: 10px;
padding-bottom: 10px;
border: 1px solid black;
text-align: center;
}
section {
width: 100%;
height: 300px;
border: 1px solid red;
}
<div class="nav-block" id="nav-bar">
<ul class="navbar-unordered-list">
<li class="link">
<a href="#1" class="active">Profile</a>
</li>
<li class="link">
<a href="#2" class="scroll">Personal Project</a>
</li>
<li class="link">
<a href="#3" class="scroll">Skills</a>
</li>
<li class="link">
<a href="#4" class="scroll">CSS Drawings</a>
</li>
<li class="link">
<a href="#5" class="scroll">Contact</a>
</li>
</ul>
</div>
<section class="sections section1" id="1">
1
</section>
<section class="sections section2" id="2">
2
</section>
<section class="sections section3" id="3">
3
</section>
<section class="sections section4" id="4">
4
</section>
<section class="sections section5" id="5">
5
</section>
Upvotes: 1
Views: 7634
Reputation: 685
You can use the jQuery. With just a few lines of code! First, put the following link inside the head:
```
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
```
Then:
```
<script>
$('#btn').click(function () {
$('body, html').animate({
'scrollTop': 100 // <--- How far from the top of the screen?100?
}, 1000);// <---time = 1s
});
</script>
```
Upvotes: -4
Reputation: 410
I have found a solution that is much more readible. Enjoy!
"use strict";
(function() {
// Scroll function
const scrollTo = (element, to, duration) => {
if (duration <= 0) {
return;
}
const difference = to - element.scrollTop;
const perTick = difference / duration * 10;
setTimeout(() => {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) {
return;
}
scrollTo(element, to, duration - 10);
}, 1);
}
// Top Navigation
// Save DOM elements that can be scrolled to
// let targetElements = {};
let targetElements = {};
(function() {
var section = document.getElementsByTagName("section");
targetElements = section;
})();
// Select links with scroll action
const scrollElements = document.getElementsByClassName('scroll');
// Add event listeners to navigation links with scroll action
Array.prototype.forEach.call(scrollElements, scrollElement => {
scrollElement.addEventListener('click', event => {
event.preventDefault(); // avoid jumping
const targetElement = targetElements[(scrollElement.getAttribute('href').slice(1))];
scrollTo(document.body, targetElement.offsetTop, 1000);
});
});
})();
Upvotes: 0
Reputation: 1074385
The reason you see it move at all is that you haven't prevented the default action of following the link, which takes you to the anchor the link references. :-)
Separately from that, the scrollTo
function shouldn't be inside the event handler.
Assuming you want to adjust the main scrollbar, I wouldn't use setInterval
, I'd use requestAnimationFrame
, see comments:
var section = document.getElementsByTagName("section"),
nav = document.getElementById("nav-bar"),
navHeight = nav.offsetHeight,
navAnchor = nav.querySelectorAll("li a"),
animate = findAnimationElement();
for (var i = 0; i < navAnchor.length; i++) {
var element = navAnchor[i];
element.addEventListener("click", function(e) {
var el = this,
id = el.getAttribute("href");
e.preventDefault(); // <=== Don't follow the link
scrollTo(document.getElementById(id.substring(1)), 300);
// Skip the "#" on "#1" -----------^^^^^^^^^^^^^
});
}
function findAnimationElement() {
// Webkit browsers animate `body`, others animate `html` (the document element)
var bodyCurrent = document.body.scrollTop;
var docElCurrent = document.documentElement.scrollTop;
document.documentElement.scrollTop = document.body.scrollTop = 10;
var animate;
if (document.body.scrollTop > 0) {
animate = document.body;
document.body.scrollTop = bodyCurrent;
} else {
animate = document.documentElement;
document.documentElement.scrollTop = docElCurrent;
}
return animate;
}
function scrollTo(to, duration) {
// When should we finish?
var finishAt = Date.now() + duration;
// Start
requestAnimationFrame(tick);
function tick() {
// How many frames left? (60fps = 16.6ms per frame)
var framesLeft = (finishAt - Date.now()) / 16.6;
// How far do we have to go?
var distance = to.getBoundingClientRect().top;
if (distance <= 0) {
// Done (this shouldn't happen, belt & braces)
return;
}
// Adjust by one frame's worth
if (framesLeft <= 1) {
// Last call
animate.scrollTop += distance;
} else {
// Not the last, adjust and schedule next
animate.scrollTop += Math.max(1, distance / framesLeft);
requestAnimationFrame(tick);
}
}
}
ul li {
list-style-type: none;
display: inline-block;
}
li a {
text-decoration: none;
display: block;
width: 120px;
padding-top: 10px;
padding-bottom: 10px;
border: 1px solid black;
text-align: center;
}
section {
width: 100%;
height: 300px;
border: 1px solid red;
}
<div class="nav-block" id="nav-bar">
<ul class="navbar-unordered-list">
<li class="link">
<a href="#1" class="active">Profile</a>
</li>
<li class="link">
<a href="#2">Personal Project</a>
</li>
<li class="link">
<a href="#3">Skills</a>
</li>
<li class="link">
<a href="#4">CSS Drawings</a>
</li>
<li class="link">
<a href="#5">Contact</a>
</li>
</ul>
</div>
<section class="sections section1" id="1">
1
</section>
<section class="sections section2" id="2">
2
</section>
<section class="sections section3" id="3">
3
</section>
<section class="sections section4" id="4">
4
</section>
<section class="sections section5" id="5">
5
</section>
Upvotes: 7
Reputation: 1
I see what you're getting at...
The only way to move the window with JS (Pure) is to create a progressive frame animation. You can do that as follows...
function animate() {
var nave = document.getElementById("navAnchor");
var id = setInterval(frame, 40);
var top = nave.offfset.top;
function frame() {
if (pos == 100) {
clearInterval(id);
} else {
pos++;
nave.style.top = pos + 'px';
}
}
}
If you are open, you're life might be simplified if you allowed for Jquery which has animation controls built in.
$("nav").click(function() {
$("#navAnchor").animate({
top: 200;
});
};
Another, less elegant, option is to shift the entire body using a CSS animation and JS button.
Upvotes: 0
Reputation: 2866
try to use this
function animate(elem, style, unit, from, to, time, prop) {
if (!elem) {
return;
}
var start = new Date().getTime(),
timer = setInterval(function () {
var step = Math.min(1, (new Date().getTime() - start) / time);
if (prop) {
elem[style] = (from + step * (to - from))+unit;
} else {
elem.style[style] = (from + step * (to - from))+unit;
}
if (step === 1) {
clearInterval(timer);
}
}, 25);
if (prop) {
elem[style] = from+unit;
} else {
elem.style[style] = from+unit;
}
}
window.onload = function () {
var target = document.getElementById("div5");
animate(document.scrollingElement || document.documentElement, "scrollTop", "", 0, target.offsetTop, 2000, true);
};
Upvotes: 0