如何暂时禁用滚动?
我正在使用scrollTo jQuery插件,并想知道是否有可能通过JavaScript暂时禁用窗口元素的滚动? 我想禁用滚动的原因是,当scrollToanimation时滚动,它变得非常丑陋;)
当然,我可以做一个$("body").css("overflow", "hidden");
然后在animation停止时将其恢复为自动,但如果滚动条仍然可见但不活动,则会更好。
scroll
事件不能被取消。 但是你可以通过取消这些交互事件来做到这一点:
鼠标 和 触摸滚动和与滚动相关的button 。
[ 工作演示 ]
// left: 37, up: 38, right: 39, down: 40, // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 var keys = {37: 1, 38: 1, 39: 1, 40: 1}; function preventDefault(e) { e = e || window.event; if (e.preventDefault) e.preventDefault(); e.returnValue = false; } function preventDefaultForScrollKeys(e) { if (keys[e.keyCode]) { preventDefault(e); return false; } } function disableScroll() { if (window.addEventListener) // older FF window.addEventListener('DOMMouseScroll', preventDefault, false); window.onwheel = preventDefault; // modern standard window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE window.ontouchmove = preventDefault; // mobile document.onkeydown = preventDefaultForScrollKeys; } function enableScroll() { if (window.removeEventListener) window.removeEventListener('DOMMouseScroll', preventDefault, false); window.onmousewheel = document.onmousewheel = null; window.onwheel = null; window.ontouchmove = null; document.onkeydown = null; }
简单地通过给身体添加一个类来实现:
.stop-scrolling { height: 100%; overflow: hidden; }
添加类然后删除当你想重新启用滚动,在IE,FF,Safari和Chrome中testing。
$('body').addClass('stop-scrolling')
对于移动设备 ,您需要处理touchmove
事件:
$('body').bind('touchmove', function(e){e.preventDefault()})
并取消绑定重新启用滚动。 在iOS6和Android 2.3.3testing
$('body').unbind('touchmove')
这是一个非常基本的方法:
window.onscroll = function () { window.scrollTo(0, 0); };
这在IE6中有些激动。
这种解决scheme将保持当前的滚动位置,而滚动禁用,不像一些跳回到顶部的用户。
它基于galambalazs的答案 ,但支持触摸设备,并重构为一个单一的对象与jquery插件包装。
在这里演示。
在github这里。
/** * $.disablescroll * Author: Josh Harrison - aloof.co * * Disables scroll events from mousewheels, touchmoves and keypresses. * Use while jQuery is animating the scroll position for a guaranteed super-smooth ride! */ ;(function($) { "use strict"; var instance, proto; function UserScrollDisabler($container, options) { // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 // left: 37, up: 38, right: 39, down: 40 this.opts = $.extend({ handleKeys : true, scrollEventKeys : [32, 33, 34, 35, 36, 37, 38, 39, 40] }, options); this.$container = $container; this.$document = $(document); this.lockToScrollPos = [0, 0]; this.disable(); } proto = UserScrollDisabler.prototype; proto.disable = function() { var t = this; t.lockToScrollPos = [ t.$container.scrollLeft(), t.$container.scrollTop() ]; t.$container.on( "mousewheel.disablescroll DOMMouseScroll.disablescroll touchmove.disablescroll", t._handleWheel ); t.$container.on("scroll.disablescroll", function() { t._handleScrollbar.call(t); }); if(t.opts.handleKeys) { t.$document.on("keydown.disablescroll", function(event) { t._handleKeydown.call(t, event); }); } }; proto.undo = function() { var t = this; t.$container.off(".disablescroll"); if(t.opts.handleKeys) { t.$document.off(".disablescroll"); } }; proto._handleWheel = function(event) { event.preventDefault(); }; proto._handleScrollbar = function() { this.$container.scrollLeft(this.lockToScrollPos[0]); this.$container.scrollTop(this.lockToScrollPos[1]); }; proto._handleKeydown = function(event) { for (var i = 0; i < this.opts.scrollEventKeys.length; i++) { if (event.keyCode === this.opts.scrollEventKeys[i]) { event.preventDefault(); return; } } }; // Plugin wrapper for object $.fn.disablescroll = function(method) { // If calling for the first time, instantiate the object and save // reference. The plugin can therefore only be instantiated once per // page. You can pass options object in through the method parameter. if( ! instance && (typeof method === "object" || ! method)) { instance = new UserScrollDisabler(this, method); } // Instance already created, and a method is being explicitly called, // eg .disablescroll('undo'); else if(instance && instance[method]) { instance[method].call(instance); } }; // Global access window.UserScrollDisabler = UserScrollDisabler; })(jQuery);
下面的解决scheme是基本的,但纯JavaScript(没有jQuery):
function disableScrolling(){ var x=window.scrollX; var y=window.scrollY; window.onscroll=function(){window.scrollTo(x, y);}; } function enableScrolling(){ window.onscroll=function(){}; }
我很抱歉回答一个旧的post,但我正在寻找一个解决scheme,并遇到了这个问题。
对于这个问题,还有许多解决方法仍然显示滚动条,如给容器100%的高度和overflow-y: scroll
样式。
在我的情况下,我刚刚创build了一个滚动条的div,我添加overflow: hidden
显示overflow: hidden
到身体:
function disableScroll() { document.getElementById('scrollbar').style.display = 'block'; document.body.style.overflow = 'hidden'; }
元素滚动条必须具有以下样式:
overflow-y: scroll; top: 0; right: 0; display: none; height: 100%; position: fixed;
这显示了一个灰色的滚动条,希望它可以帮助未来的游客。
根据galambalazs的post,我会添加对触摸设备的支持,允许我们触摸但不向上或向下滚动:
function disable_scroll() { ... document.ontouchmove = function(e){ e.preventDefault(); } } function enable_scroll() { ... document.ontouchmove = function(e){ return true; } }
我一直在寻找解决这个问题的方法,但对上述任何解决scheme都不满意( 就像写这个答案一样 ),所以我想出了这个解决scheme。
CSS
.scrollDisabled { position: fixed; margin-top: 0;// override by JS to use acc to curr $(window).scrollTop() width: 100%; }
JS
var y_offsetWhenScrollDisabled=0; function disableScrollOnBody(){ y_offsetWhenScrollDisabled= $(window).scrollTop(); $('body').addClass('scrollDisabled').css('margin-top', -y_offsetWhenScrollDisabled); } function enableScrollOnBody(){ $('body').removeClass('scrollDisabled').css('margin-top', 0); $(window).scrollTop(y_offsetWhenScrollDisabled); }
这个怎么样? (如果你使用jQuery)
var $window = $(window); var $body = $(window.document.body); window.onscroll = function() { var overlay = $body.children(".ui-widget-overlay").first(); // Check if the overlay is visible and restore the previous scroll state if (overlay.is(":visible")) { var scrollPos = $body.data("scroll-pos") || { x: 0, y: 0 }; window.scrollTo(scrollPos.x, scrollPos.y); } else { // Just store the scroll state $body.data("scroll-pos", { x: $window.scrollLeft(), y: $window.scrollTop() }); } };
我正在使用showModalDialog ,将辅助页面显示为模式对话框。
隐藏主窗口滚动条:
document.body.style.overflow = "hidden";
当closures模式对话框时,显示主窗口滚动条:
document.body.style.overflow = "scroll";
从对话框访问主窗口中的元素:
parent.document.getElementById('dialog-close').click();
只是为了searchshowModalDialog的任何人:(在原始代码的第29行之后)
document.getElementById('dialog-body').contentWindow.dialogArguments = arg; document.body.style.overflow = "hidden";//**** document.getElementById('dialog-close').addEventListener('click', function(e) { e.preventDefault(); document.body.style.overflow = "scroll";//**** dialog.close(); });
另一个scheme
body { overflow-y: scroll; width: 100%; margin: 0 auto; }
这样你总是有一个垂直的滚动条,但是由于我的大部分内容比视口更长,这对我来说还是可以的。 内容以一个单独的div为中心,但是没有在body中再次设置边距,我的内容将停留在左侧。
这些是我用来显示popup窗口/模态的两个函数:
var popup_bodyTop = 0; var popup_bodyLeft = 0; function popupShow(id) { $('#'+ id).effect('fade'); $('#popup-overlay').effect('fade'); // remember current scroll-position // because when setting/unsetting position: fixed to body // the body would scroll to 0,0 popup_bodyLeft = $(document).scrollLeft(); popup_bodyTop = $(document).scrollTop(); // invert position var x = - popup_bodyLeft; var y = - popup_bodyTop; $('body').css('position', 'fixed'); $('body').css('top', y.toString() +'px'); $('body').css('left', x.toString() +'px'); } function popupHide(id) { $('#'+ id).effect('fade'); $('#popup-overlay').effect('fade'); $('body').css('position', ''); $('html, body').scrollTop(popup_bodyTop); $('html, body').scrollLeft(popup_bodyLeft); }
结果:由于左侧滚动条,不可滚动的背景和内容不重新定位。 testing目前的FF,Chrome和IE 10。
根据您想要使用删除的滚动来实现的目标,您可以修改要删除滚动的元素(点击时,或者您想要暂时停用滚动的任何其他触发器)
我四处寻找“临时不卷动”解决scheme,并根据我的需要,解决了这个问题
上课
.fixed{ position: fixed; }
然后用Jquery
var someTrigger = $('#trigger'); //a trigger button var contentContainer = $('#content'); //element I want to temporarily remove scroll from contentContainer.addClass('notfixed'); //make sure that the element has the "notfixed" class //Something to trigger the fixed positioning. In this case we chose a button. someTrigger.on('click', function(){ if(contentContainer.hasClass('notfixed')){ contentContainer.removeClass('notfixed').addClass('fixed'); }else if(contentContainer.hasClass('fixed')){ contentContainer.removeClass('fixed').addClass('notfixed'); }; });
我发现这是一个足够简单的解决scheme,可以在所有浏览器上正常工作,并且可以在便携式设备(如iPhone,平板电脑等)上使用。 由于元素是暂时固定的,没有滚动:)
注意! 根据“contentContainer”元素的位置,您可能需要从左侧进行调整。 当固定类处于活动状态时,可以通过向该元素添加一个css left值来轻松完成此操作
contentContainer.css({ 'left': $(window).width() - contentContainer.width()/2 //This would result in a value that is the windows entire width minus the element we want to "center" divided by two (since it's only pushed from one side) });
在我接受的答案中取消事件是一种可怕的方法:
相反,我使用的position: fixed; top: -scrollTop();
position: fixed; top: -scrollTop();
下面。
演示: https : //jsfiddle.net/w9w9hthy/5/
从我的jQuerypopup项目: https : //github.com/seahorsepip/jPopup
//Freeze page content scrolling function freeze() { if($("html").css("position") != "fixed") { var top = $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop(); if(window.innerWidth > $("html").width()) { $("html").css("overflow-y", "scroll"); } $("html").css({"width": "100%", "height": "100%", "position": "fixed", "top": -top}); } } //Unfreeze page content scrolling function unfreeze() { if($("html").css("position") == "fixed") { $("html").css("position", "static"); $("html, body").scrollTop(-parseInt($("html").css("top"))); $("html").css({"position": "", "width": "", "height": "", "top": "", "overflow-y": ""}); } }
这段代码考虑了宽度,高度,滚动条和页面跳转问题。
上面的代码解决了可能的问题:
- 宽度,当设置位置固定时,html元素宽度可以小于100%
- 身高,和上面一样
- 滚动条,当设置位置固定的页面内容不再有一个滚动条,即使它有一个滚动条之前导致水平页面跳转
- pagejump,当设置位置固定页面scrollTop不再有效,导致垂直pagejump
如果有人对上面的页面冻结/解冻代码有任何改进,让我知道,所以我可以将这些改进添加到我的项目。
build立在夏安福布斯的答案,和我通过fcalderan在这里find一个: 只是禁用滚动不隐藏它? 并修复Hallodom的滚动条消失的问题
CSS:
.preventscroll{ position: fixed; overflow-y:scroll; }
JS:
whatever.onclick = function(){ $('body').addClass('preventscroll'); } whatevertoclose.onclick = function(){ $('body').removeClass('preventscroll'); }
这段代码确实会跳转到页面的顶部,但我认为fcalderan的代码有一个解决方法。
我知道这是一个古老的问题,但我必须做一些非常相似的事情,经过一段时间寻找答案并尝试不同的方法,我最终使用了一个非常简单的解决scheme。
我的问题是非常相似,几乎相同,唯一的区别是我没有实际显示滚动条 – 我只是要确保它的宽度仍然会被使用,所以当我的覆盖显示时,页面的宽度不会改变。
当我开始将覆盖层滑入屏幕时,我会:
$('body').addClass('stop-scrolling').css('margin-right', 8);
当我从屏幕上滑动覆盖层后,我会:
$('body').removeClass('stop-scrolling').css('margin-right', 0);
重要提示:这是完美的作品,因为我的覆盖是absolute
定位的, right: 0px
visible
。
我在另一个网站上find了这个答案:
禁用滚动:
$( ".popup").live({ popupbeforeposition: function(event, ui) { $("body").on("touchmove", false); } });
closurespopup窗口后,滚动:
$( ".popup" ).live({ popupafterclose: function(event, ui) { $("body").unbind("touchmove"); } });
galambalazs的解决scheme是伟大的! 它在Chrome和Firefox中都能很好地工作。 而且它也可以扩展到阻止浏览器窗口的任何默认事件。 假设您正在canvas上做一个应用程序。 你可以这样做:
var events = { preventDefault: function(e) { e = e || window.event; if (e.preventDefault) e.preventDefault(); e.returnValue = false; }, //spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36, //left: 37, up: 38, right: 39, down: 40 keys: [32, 33, 34, 35, 36, 37, 38, 39, 40], keydown: function(e) { for (var i = events.keys.length; i--;) { if (e.keyCode === events.keys[i]) { events.preventDefault(e); return; } } }, wheel: function(e) { events.preventDefault(e); }, disable: function() { if (window.addEventListener) { window.addEventListener('DOMMouseScroll', events.wheel, false); } window.onmousewheel = document.onmousewheel = events.wheel; document.onkeydown = helpers.events.keydown; }, enable: function() { if (window.removeEventListener) { window.removeEventListener('DOMMouseScroll', events.wheel, false); } window.onmousewheel = document.onmousewheel = document.onkeydown = null; } }
然后在你的应用程序中,假设你要处理自己的事件,比如鼠标,键盘,触摸事件等等……当鼠标进入canvas内部时,可以禁用默认事件,当鼠标重新启用时出去:
function setMouseEvents(canvas) { var useCapture = false; //Mouse enter event canvas.addEventListener('mouseenter', function(event) { events.disable(); }, useCapture); //Mouse leave event canvas.addEventListener('mouseleave', function(event) { events.enable(); }, useCapture); }
你甚至可以用这个黑客禁用右键菜单:
function disableRightClickMenu(canvas) { var my_gradient = canvas.context.createLinearGradient(0, 0, 0, 225); my_gradient.addColorStop(0, "white"); my_gradient.addColorStop(1, "white"); canvas.context.fillStyle = my_gradient; canvas.context.fillRect(0, 0, canvas.width, canvas.height); canvas.oncontextmenu = function() { return false; }; }
我在手机屏幕上有类似的animation问题,但在笔记本电脑上,当试图使用jquery的animation命令来animation一个div的时候,这个问题不是。 所以我决定使用一个定时器来恢复窗口的滚动位置,以便肉眼看到文档看起来是静态的。 这个解决scheme在三星Galaxy-2或iphone-5这样的小屏幕移动设备上完美工作。
这种方法的主要逻辑 :设置窗口的滚动位置为原始滚动位置的计时器应在jqueryanimation命令之前启动,然后当animation完成时,我们需要清除此计时器( original scroll position
是animation开始之前的位置) 。
我惊喜地发现,如果计时器间隔为1 millisecond
,那么文档在animation持续时间内实际上显示为静态,这正是我所期望的。
//get window scroll position prior to animation //so we can keep this position during animation var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft; var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop; //NOTE:restoreTimer needs to be global variable //start the restore timer restoreTimer = setInterval(function() { window.scrollTo(xPosition, yPosition); }, 1); //animate the element emt emt.animate({ left: "toggle", top: "toggle", width: "toggle", height: "toggle" }, 500, function() { //when animation completes, we stop the timer clearInterval(restoreTimer); });
另一个解决scheme :根据Mohammad Anini在这篇文章中回答启用/禁用滚动,我还发现一个修改后的代码如下。
//get current scroll position var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft; var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop; //disable scrolling window.onscroll = function() { window.scrollTo(xPosition, yPosition); }; //animate and enable scrolling when animation is completed emt.animate({ left: "toggle", top: "toggle", width: "toggle", height: "toggle" }, 500, function() { //enable scrolling when animation is done window.onscroll = function() {}; });
一个简单的解决scheme,为我工作(暂时禁用窗口滚动)。
基于这个小提琴: http : //jsfiddle.net/dh834zgw/1/
以下片段(使用jquery)将禁用窗口滚动:
var curScrollTop = $(window).scrollTop(); $('html').toggleClass('noscroll').css('top', '-' + curScrollTop + 'px');
并在您的CSS:
html.noscroll{ position: fixed; width: 100%; top:0; left: 0; height: 100%; overflow-y: scroll !important; z-index: 10; }
现在,当您删除模式时,不要忘记删除html标签上的noscroll类:
$('html').toggleClass('noscroll');
我刚刚放在一起的东西:
的jsfiddle
document.onwheel = function(e) { // get the target element target = e.target; // the target element might be the children of the scrollable element // eg, "li"s inside an "ul", "p"s inside a "div" etc. // we need to get the parent element and check if it is scrollable // if the parent isn't scrollable, we move up to the next parent while (target.scrollHeight <= target.clientHeight) { // while looping parents, we'll eventually reach document.body // since body doesn't have a parent, we need to exit the while loop if (target == document.body) { break; } target = target.parentElement; } // we want this behaviour on elements other than the body if (target != document.body) { // if the scrollbar is at the top and yet if it still tries to scroll up // we prevent the scrolling if (target.scrollTop <= 0 && e.deltaY < 0) { e.preventDefault(); } // similarly, if the scrollbar is at the bottom and it still tries to scroll down // we prevent it else if (target.clientHeight + target.scrollTop >= target.scrollHeight && e.deltaY > 0) { e.preventDefault(); } } };
body { background: gainsboro; } #box { width: 300px; height: 600px; padding: 5px; border: 1px solid silver; margin: 50px auto; background: white; overflow: auto; }
<div id="box"> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </div>
您可以阻止空格键滚动并隐藏浏览器滚动条:
$(document).keydown(function(event) { if (event.keyCode == 32) { return false; } }); document.documentElement.style.overflow = 'hidden'; document.body.scroll = 'no';
我对这个问题的看法还包括对身宽的关注,因为当我们用overflow = "hidden"
隐藏滚动条的时候,页面似乎会跳舞一点。 下面的代码完全适合我,并且基于Angular方法。
element.bind('mouseenter', function() { var w = document.body.offsetWidth; document.body.style.overflow = 'hidden'; document.body.style.width = w + 'px'; }); element.bind('mouseleave', function() { document.body.style.overflow = 'initial'; document.body.style.width = 'auto'; });
从Chrome 56和其他现代浏览器开始,必须为addEventListener
调用添加passive:false
,以使preventDefault
正常工作。 所以我用这个来停止在手机上滚动:
function preventDefault(e){ e.preventDefault(); } function disableScroll(){ document.body.addEventListener('touchmove', preventDefault, { passive: false }); } function enableScroll(){ document.body.removeEventListener('touchmove', preventDefault, { passive: false }); }
我发现了一个更好的,但错误的方式,结合sdleihssirhc的想法:
window.onscroll = function() { window.scrollTo(window.scrollX, window.scrollY); //Or //window.scroll(window.scrollX, window.scrollY); //Or Fallback //window.scrollX=window.scrollX; //window.scrollY=window.scrollY; };
我没有testing,但我会稍后编辑,让大家知道。 我85%确定它可以在主stream浏览器上运行。
用JavaScript启用下面的CSS将会有所帮助。 我不像其他人那样好,但这对我有效。
body { position: fixed; overflow-y: scroll; }