用纯JavaScript滚动动画

时间:2017-04-29 16:03:02

标签: javascript

我正在尝试在访问者点击锚点时构建滚动动画部分。你可能会注意到变量" id"将显示#1,这将匹配部分本身的id值。如何将滚动动画添加到此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);
    }
  });
}
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;

5 个答案:

答案 0 :(得分:1)

你看到它移动的原因是你没有阻止跟随链接的默认操作,这会将你带到链接引用的锚点。 : - )

除此之外,scrollTo函数不应该在事件处理程序中。

假设您要调整主滚动条,我不会使用setInterval,我会使用requestAnimationFrame,请参阅注释:

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>

答案 1 :(得分:0)

尝试使用此

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

答案 2 :(得分:0)

我看到你正在得到什么......

使用JS(Pure)移动窗口的唯一方法是创建渐进式帧动画。你可以这样做......

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

如果你是开放的,如果你允许使用内置动画控件的Jquery,你的生活可能会被简化。

$("nav").click(function() {
    $("#navAnchor").animate({
        top: 200;
    });
};

另一个不太优雅的选择是使用CSS动画和JS按钮移动整个身体。

答案 3 :(得分:0)

我找到了一种更易读的解决方案。享受!

&#13;
&#13;
"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);
	});
});
})();
&#13;
&#13;
&#13;

答案 4 :(得分:-2)

您可以使用 jQuery。 只需几行代码! 首先,将以下链接放入头部:

    ```
    <script
    src="https://code.jquery.com/jquery-3.5.1.min.js"
    integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
    crossorigin="anonymous"></script>
    ```

那么:

    ```
    <script>            
    $('#btn').click(function () {
            $('body, html').animate({
                'scrollTop': 100 // <--- How far from the top of the screen?100?
            }, 1000);// <---time = 1s
        });
    </script>
    ```