javascript - 在 Vanilla javascript 中鼠标滚轮上的平滑垂直滚动?

标签 javascript mouseevent mouselistener mousewheel

我是 vanilla javascript 的 super 粉丝,目前我正在做一个项目,我需要在鼠标滚轮上实现平滑滚动。我想使用 vanilla JS 来实现它。 我在做一些研究时发现了一个 jQuery 片段,如下所示。

$(window).on('mousewheel DOMMouseScroll', function(e) {
   var dir,
   amt = 100;

   e.preventDefault();
   if(e.type === 'mousewheel') {
     dir = e.originalEvent.wheelDelta > 0 ? '-=' : '+=';
   }
   else {
     dir = e.originalEvent.detail < 0 ? '-=' : '+=';
   }      

   $('html, body').stop().animate({
     scrollTop: dir + amt
   },500, 'linear');
});

谁能帮我解决如何在不使用像 jQuery 或任何其他库这样的辅助库的情况下实现平滑滚动的问题。

人们用 jQuery 完成了很多实现。但我想要一个可以在 vanilla JS 中完成的最佳实现。这可以在任何地方的 React、Angular 和 Vue 中实现。

最佳答案

这个怎么样:

function init(){
	new SmoothScroll(document,120,12)
}

function SmoothScroll(target, speed, smooth) {
	if (target === document)
		target = (document.scrollingElement 
              || document.documentElement 
              || document.body.parentNode 
              || document.body) // cross browser support for document scrolling
      
	var moving = false
	var pos = target.scrollTop
  var frame = target === document.body 
              && document.documentElement 
              ? document.documentElement 
              : target // safari is the new IE
  
	target.addEventListener('mousewheel', scrolled, { passive: false })
	target.addEventListener('DOMMouseScroll', scrolled, { passive: false })

	function scrolled(e) {
		e.preventDefault(); // disable default scrolling

		var delta = normalizeWheelDelta(e)

		pos += -delta * speed
		pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight)) // limit scrolling

		if (!moving) update()
	}

	function normalizeWheelDelta(e){
		if(e.detail){
			if(e.wheelDelta)
				return e.wheelDelta/e.detail/40 * (e.detail>0 ? 1 : -1) // Opera
			else
				return -e.detail/3 // Firefox
		}else
			return e.wheelDelta/120 // IE,Safari,Chrome
	}

	function update() {
		moving = true
    
		var delta = (pos - target.scrollTop) / smooth
    
		target.scrollTop += delta
    
		if (Math.abs(delta) > 0.5)
			requestFrame(update)
		else
			moving = false
	}

	var requestFrame = function() { // requestAnimationFrame cross browser
		return (
			window.requestAnimationFrame ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame ||
			window.oRequestAnimationFrame ||
			window.msRequestAnimationFrame ||
			function(func) {
				window.setTimeout(func, 1000 / 50);
			}
		);
	}()
}
p{
  font-size: 16pt;
  margin-bottom: 30%;
}
<body onload="init()">
  <h1>Lorem Ipsum</h1>
  
  <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  
  <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  
  <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</body>

通过调用 new SmoothScroll(target,speed,smooth) 使用它

参数:

  1. target:要平滑滚动的元素 - 可以是 div 或 document
  2. 速度:每个鼠标滚轮滚动的像素数量 步骤
  3. smooth:平滑系数,值越大越平滑 顺利。

感谢@Phrogz 提供 mousewheel normalization .

编辑:自 Chrome 73 起,需要将 mousewheel 事件的事件监听器标记为非被动的,以便能够对其调用 preventDefault() .感谢@Fred K。

关于javascript - 在 Vanilla javascript 中鼠标滚轮上的平滑垂直滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47011055/

相关文章:

javascript - 在javascript中使用变量作为 'id'属性

javascript - Jest 不适用于 util.promisify(setTimeout)

javascript - 在 Internet Explorer 中使用 JavaScript,如何在不刷新页面的情况下清除内存?

objective-c - 如何检测鼠标悬停在 NSButton 上。 Obj-C, cocoa

Java:JFrame 与 MouseListener、KeyListener 和 PaintComponent 相关的问题

java - 检测单击了哪个 JLabel

javascript - Jquery Ajax将数据传递到另一个php文件来更新数据库只允许更新一次(Wordpress)

javascript - 如何启用拖动控件来滚动和扩展选择

java - 拖动未修饰的 JFrame 并调整其大小

java - 运动中图形对象的鼠标监听器