1

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>

4
  • 2
    "There are tons of examples of scroll animations in jQuery, but not much of JavaScript." The jQuery ones are in JavaScript. They're just using jQuery instead of using the DOM directly. Commented Apr 29, 2017 at 16:05
  • I meant vanilla JavaScript Commented Apr 29, 2017 at 16:08
  • You need to preventDefault Commented Apr 29, 2017 at 16:11
  • 1
    It's still vanilla JavaScript. Using a library doesn't change the language you're working with. The distinction is between "using jQuery" and "using the DOM directly," it has nothing whatsoever to do with the language. Commented Apr 29, 2017 at 16:11

5 Answers 5

7

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>

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your help
One more thing, I have set the navbar with position: fixed; This function will only scroll down, but not up.....
@Front-endDeveloper: That may be as simple as changing the if (distance <= 0) check to if (distance == 0). :-)
@Front-endDeveloper To scroll back up, besides the mentioned if (distance == 0), I had to remove the Math.max(); resulting in animate.scrollTop += distance / framesLeft;
0

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);
};

Comments

0

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.

Comments

0

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);
	});
});
})();

Comments

-4

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>
    ```

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.