จะปิดการใช้งานการเลื่อนชั่วคราวได้อย่างไร?


434

ฉันใช้ปลั๊กอิน scrollTo jQuery และต้องการทราบว่าเป็นไปได้ไหมที่จะปิดการใช้งานการเลื่อนบนองค์ประกอบหน้าต่างผ่าน Javascript ชั่วคราว เหตุผลที่ฉันต้องการปิดการเลื่อนคือเมื่อคุณเลื่อนในขณะที่ scrollTo กำลังเคลื่อนไหวมันน่าเกลียดจริงๆ)

แน่นอนฉันสามารถทำ$("body").css("overflow", "hidden");แล้วนำกลับไปที่อัตโนมัติเมื่อภาพเคลื่อนไหวหยุดลง แต่จะดีกว่าถ้าแถบเลื่อนยังคงมองเห็นได้ แต่ไม่ทำงาน


12
หากยังคงแสดงอยู่ผู้ใช้จะได้รับการฝึกฝนให้คิดว่าต้องใช้งานได้ หากปริมาณที่ไม่ได้ย้ายหรือปริมาณไม่ตอบสนองก็จะทำลายรูปแบบจิตผู้ใช้ของวิธีการที่หน้าคุณทำงานและทำให้เกิดความสับสน ฉันจะหาวิธีที่ดีกว่าในการรับมือกับการเลื่อนขณะเคลื่อนไหวเช่นหยุดเคลื่อนไหว
Marcus Whybrow

วิธีแก้ปัญหาอื่น: stackoverflow.com/questions/9280258/…
gdbj

คำตอบ:


730

scrollเหตุการณ์ไม่สามารถยกเลิก แต่คุณสามารถทำได้โดยยกเลิกกิจกรรมการโต้ตอบเหล่านี้: เลื่อน
เมาส์ และ Touchและปุ่มที่เกี่ยวข้องกับการเลื่อน

[ สาธิตการทำงาน ]

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

function preventDefaultForScrollKeys(e) {
  if (keys[e.keyCode]) {
    preventDefault(e);
    return false;
  }
}

// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
  window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
    get: function () { supportsPassive = true; } 
  }));
} catch(e) {}

var wheelOpt = supportsPassive ? { passive: false } : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

// call this to Disable
function disableScroll() {
  window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
  window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
  window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
  window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}

// call this to Enable
function enableScroll() {
  window.removeEventListener('DOMMouseScroll', preventDefault, false);
  window.removeEventListener(wheelEvent, preventDefault, wheelOpt); 
  window.removeEventListener('touchmove', preventDefault, wheelOpt);
  window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}

อัปเดต: แก้ไขเดสก์ท็อป Chrome และเบราว์เซอร์มือถือที่ทันสมัยพร้อมฟังแบบพาสซีฟ


114
เคล็ดลับสำหรับผู้พัฒนารายอื่นที่ติดอยู่ในกับดักนี้: ตรวจสอบให้แน่ใจว่าคุณได้ลบการโทร 'e.stopPropagation ()' ใด ๆ และทั้งหมดออกจาก jQuery อื่น ๆ ที่พยายามหยุดการเลื่อนเนื่องจากไม่เพียง แต่จะไม่ทำงานเท่านั้น มันใช้ได้ผล หวังว่าฉันสูญเสียไป 30 นาทีจะช่วยประหยัดเวลาคนอื่น :)
เดิร์คฟานเบอร์เกน

4
คุณสามารถเพิ่ม 32 (ช่องว่าง) ลงในอาร์เรย์คีย์ที่ปิดใช้งาน (แสดงในความคิดเห็นของโค้ด)
gblazex

14
ฉันสามารถเลื่อนหน้าจอแบบนี้ได้ตลอดเวลา: ใช้ปุ่มกลางกดและเลื่อนเม้าส์ ... ดังนั้นเคล็ดลับนี้จะไม่ส่งผลกระทบต่อผู้ใช้เช่นฉัน;)
Denis V

11
แถบเลื่อนไม่ถูกปิดใช้งาน
จริง

8
ไม่สามารถใช้งานได้กับ Chrome อีกต่อไป
PerrierCitror

427

ทำได้โดยเพิ่มคลาสเข้ากับร่างกาย:

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}

เพิ่มคลาสจากนั้นลบเมื่อคุณต้องการเปิดใช้งานการเลื่อนอีกครั้งทดสอบใน IE, FF, Safari และ Chrome

$('body').addClass('stop-scrolling')

สำหรับอุปกรณ์มือถือคุณจะต้องจัดการกับtouchmoveเหตุการณ์:

$('body').bind('touchmove', function(e){e.preventDefault()})

และยกเลิกการผูกเพื่อเปิดใช้งานการเลื่อนอีกครั้ง ทดสอบใน iOS6 และ Android 2.3.3

$('body').unbind('touchmove')

4
เข้าใจแล้ว! คุณต้องจัดการกับเหตุการณ์เช่นเดียวกับtouchmove $('body').bind('touchmove', function(e){e.preventDefault()})แก้ไขคำตอบนี้เพื่อรวมโซลูชันมือถือนี้
MusikAnimal

3
เยี่ยมเพียงแค่ต้องแน่ใจว่าการเลื่อนภายในใด ๆ สามารถทำงานในโหมดโมดัลสำหรับอุปกรณ์สัมผัสได้ สามารถวางซ้อนทับใต้โมดัลและป้องกัน touchmove ปริยายบนโอเวอร์เลย์แทนที่จะเป็นบอดี้
hallodom

63
ในขณะที่วิธีนี้ใช้งานได้ แต่มีผลที่ไม่พึงประสงค์ (อาจ) ของการเลื่อนกลับไปที่ด้านบนของหน้า
Matt

3
สิ่งนี้ไม่ได้ผลสำหรับฉันเว้นแต่ตัวเลือกของฉันคือ$('body,html')
PickYourPoison

22
วิธีนี้ใช้ได้ผล แต่แถบเลื่อนจะหายไปและสร้างเอฟเฟกต์ 'bump' (ใต้หน้าต่างระบบปฏิบัติการ) เมื่อคุณใช้คลาสนี้กับร่างกาย (ตัวอย่าง)
Georgio

57

นี่เป็นวิธีพื้นฐานจริงๆที่จะทำ:

window.onscroll = function () { window.scrollTo(0, 0); };

มันเป็นเรื่องที่น่ากลัวใน IE6


14
ไม่ใช่การปิดการใช้งานจริง ๆ เช่น snap เป็นค่าเริ่มต้นมากขึ้นเมื่อพยายามเลื่อน
มาร์คัส Whybrow

11
@ Marcus ดีพอ ๆ กับเหตุการณ์ที่ไม่สามารถยกเลิกได้
sdleihssirhc

3
แม้ว่ามันจะไม่ปิดการใช้งานจริง แต่ก็จำลองได้และมันก็ดีพอสำหรับฉัน
Chris Bier

11
IMHO - คำตอบที่ดีที่สุดที่นี่ นอกจากนี้คุณไม่จำเป็นต้องล็อคมัน(0, 0)เพียงแค่ใช้ตำแหน่งการเลื่อนปัจจุบัน
YemSalat

4
แต่เราจะเปิดใช้งานอีกครั้งได้อย่างไร
Cybernetic

41

วิธีแก้ปัญหาต่อไปนี้เป็นพื้นฐาน แต่เป็นจาวาสคริปต์ที่บริสุทธิ์ (ไม่ใช่ jQuery):

function disableScrolling(){
    var x=window.scrollX;
    var y=window.scrollY;
    window.onscroll=function(){window.scrollTo(x, y);};
}

function enableScrolling(){
    window.onscroll=function(){};
}

3
Jumpy ใน Safari 7.1 และ IE 11 ใหม่ล่าสุดสำหรับ Chrome, Firefox, Opera
Timo Kähkönen

ยังเป็นเรื่องเล็กน้อยที่น่าแปลกใจสำหรับ Chrome รุ่นใหม่ล่าสุด
Jason Allshorn

ทำงานได้ดีในซาฟารีโครเมี่ยม แต่กระพริบใน IE
Bhuvan Arora

หากวิธีนี้ใช้ไม่ได้กับเบราว์เซอร์บางตัวแสดงว่าเป็นปัญหาของเบราว์เซอร์
Oto Shavadze

ตามที่กล่าวไว้ในคำตอบอื่นscroll-behavior: smoothบอร์กนี้ นอกจากนี้ฉันไม่เห็นด้วยกับ Oto บอกว่ามันเป็นความผิดของเบราว์เซอร์ คุณกำลังสมมติว่ามีบางสิ่งจะเกิดขึ้นทันทีเมื่อในความเป็นจริงมันไม่ตรงกัน
Matt Fletcher

25

โซลูชันนี้จะรักษาตำแหน่งการเลื่อนปัจจุบันในขณะที่การเลื่อนถูกปิดใช้งานซึ่งแตกต่างจากการเลื่อนผู้ใช้กลับไปด้านบน

มันขึ้นอยู่กับคำตอบของ galambalazsแต่ด้วยการรองรับอุปกรณ์สัมผัสและได้รับการปรับโครงสร้างใหม่เป็นวัตถุชิ้นเดียวด้วย jquery plugin wrapper

ตัวอย่างที่นี่

บน 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,
        // e.g. .disablescroll('undo');
        else if(instance && instance[method]) {
            instance[method].call(instance);
        }

    };

    // Global access
    window.UserScrollDisabler = UserScrollDisabler;

})(jQuery);

ดีใจที่มีประโยชน์ NB ผมได้แก้ไขด้วยการเชื่อมโยงไปนี้ในรูปแบบปลั๊กอิน jQuery
Josh Harrison

อาจช่วยได้ถ้าปุ่มเลื่อนปิดใช้งานใช้งานได้จริง
cameronjonesweb

@ user1672694 สามารถใช้งานได้ใน Chrome เบราว์เซอร์ของคุณคืออะไรและหน้าสาธิตใดที่คุณพบข้อผิดพลาด มีข้อผิดพลาด JS ในคอนโซลหรือไม่
Josh Harrison

ใน Chrome (38, Windows 7) ฉันยังคงสามารถเลื่อนได้โดยคลิกปุ่มกลางค้างไว้แล้วลาก
Sethi

1
โปรดเพิกเฉยฉันพบว่าการเชื่อมโยงมันใช้mousewheelงานได้มีเสน่ห์
adamj

17

ฉันขอโทษที่จะตอบโพสต์เก่า แต่ฉันกำลังมองหาวิธีการแก้ปัญหาและเจอคำถามนี้

มีวิธีแก้ไขปัญหามากมายสำหรับปัญหานี้ในการแสดงแถบเลื่อนเช่นให้ความสูง 100% และคอนเทนเนอร์ overflow-y: scrollสไตล์

ในกรณีของฉันฉันเพิ่งสร้าง div ด้วย scrollbar ที่ฉันแสดงขณะเพิ่ม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;

นี่เป็นแถบเลื่อนสีเทาหวังว่ามันจะช่วยผู้เยี่ยมชมในอนาคต


8

ฉันกำลังมองหาวิธีแก้ไขปัญหานี้ แต่ไม่พอใจกับวิธีแก้ไขปัญหาใด ๆ ข้างต้น ( เหมือนการเขียนคำตอบนี้ ) ดังนั้นฉันจึงหาวิธีแก้ปัญหานี้ ..

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

ฉันพบนี้ทำงานให้ฉันถ้าฉันเพิ่มoverflow-y: scrollไปยัง.scrollDisabledรูปแบบ มิฉะนั้นจะมีการกระโดดเล็กน้อยเนื่องจาก scrollbar ซ่อนอยู่ทุกครั้ง แน่นอนว่าใช้งานได้กับฉันเท่านั้นเพราะหน้าเว็บของฉันใช้เวลานานพอที่จะต้องใช้แถบเลื่อนแม้แต่กับจอแสดงผลขนาดใหญ่ที่สุด
Andrew Miner

7

ตามประกาศของgalambalazsฉันจะเพิ่มการรองรับอุปกรณ์สัมผัสช่วยให้เราสามารถสัมผัส แต่ไม่มีการเลื่อนขึ้นหรือลง:

function disable_scroll() {
   ...
   document.ontouchmove = function(e){ 
        e.preventDefault(); 
   }
}

function enable_scroll() {
   ...
   document.ontouchmove = function(e){ 
     return true; 
   }
}

3
คุณแน่ใจหรือว่ามันเป็นคำตอบไม่ใช่แค่ความเห็นของคำตอบอื่น ๆ ?
IvanH

6

ในฐานะที่เป็น Chrome 56 และเบราว์เซอร์สมัยใหม่อื่น ๆ คุณต้องเพิ่มpassive:falseในการaddEventListenerโทรเพื่อpreventDefaultทำงาน ดังนั้นฉันใช้สิ่งนี้เพื่อหยุดเลื่อนบนมือถือ:

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault, { passive: false });
}

5

ไม่ฉันจะไม่ไปกับการจัดการกิจกรรมเพราะ:

  • ไม่รับประกันว่าเหตุการณ์ทั้งหมดจะไปถึงร่างกาย

  • การเลือกข้อความและเลื่อนลงด้านล่างจะเป็นการเลื่อนเอกสารจริงๆ

  • ถ้าในขั้นตอนของการปลดเหตุการณ์ sth ผิดพลาดคุณถึงวาระ

ฉันถูกมันกัดโดยการทำ copy-paste พร้อม textarea ที่ซ่อนอยู่และเดาว่าอะไรเลื่อนหน้าทุกครั้งที่ฉันทำ copy เพราะภายในฉันต้องเลือก textarea ก่อนที่ฉันจะโทร document.execCommand('copy')ก่อนที่ผมจะโทร

อย่างไรก็ตามนั่นคือวิธีที่ฉันไปสังเกตเห็นsetTimeout():

document.body.setAttribute('style','overflow:hidden;');
// do your thing...
setTimeout(function(){document.body.setAttribute('style','overflow:visible;');}, 500);

โมเมนตัมกระพริบอยู่เมื่อแถบเลื่อนหายไปครู่หนึ่ง แต่เป็นที่ยอมรับของฉัน


4

คุณสามารถแก้ไของค์ประกอบที่คุณต้องการลบการเลื่อนได้ (ขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุจากการเลื่อนออก (เมื่อคลิกหรือทริกเกอร์อื่น ๆ ที่คุณต้องการปิดการเลื่อนชั่วคราว)

ฉันกำลังค้นหาโซลูชัน "temp no scroll" และสำหรับความต้องการของฉันสิ่งนี้ก็แก้ไขได้

ทำชั้นเรียน

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

ฉันพบว่านี่เป็นวิธีแก้ปัญหาที่ง่ายพอที่ทำงานได้ดีบนเบราว์เซอร์ทั้งหมดและยังทำให้ใช้งานได้ง่ายบนอุปกรณ์พกพา (เช่น iPhone, แท็บเล็ตและอื่น ๆ ) เนื่องจากองค์ประกอบได้รับการแก้ไขชั่วคราวจึงไม่มีการเลื่อน :)

บันทึก! ทั้งนี้ขึ้นอยู่กับตำแหน่งขององค์ประกอบ "contentContainer" ของคุณคุณอาจต้องปรับเปลี่ยนจากด้านซ้าย ซึ่งสามารถทำได้อย่างง่ายดายโดยการเพิ่มค่า css left ให้กับองค์ประกอบนั้นเมื่อคลาส fixed ใช้งานอยู่

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

4

ทางออกอื่น:

body {
    overflow-y: scroll;
    width: 100%;
    margin: 0 auto;
}

ด้วยวิธีนี้คุณจะมีแถบเลื่อนแนวตั้งเสมอ แต่เนื้อหาส่วนใหญ่ของฉันยาวกว่าวิวพอร์ตจึงเหมาะสำหรับฉัน เนื้อหาอยู่ตรงกลางด้วย div แยก แต่ไม่มีการตั้งระยะขอบอีกครั้งในเนื้อหาเนื้อหาของฉันจะอยู่ทางซ้าย

นี่เป็นฟังก์ชันสองอย่างที่ฉันใช้เพื่อแสดงป๊อปอัป / โมดอลของฉัน:

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

ผลลัพธ์: พื้นหลังที่ไม่สามารถเลื่อนได้และไม่มีการวางตำแหน่งเนื้อหาอีกครั้งเนื่องจากแถบเลื่อนด้านซ้าย ทดสอบกับ FF ปัจจุบัน, Chrome และ IE 10


สิ่งนี้ใช้ได้สำหรับฉันและปัญหาการเลื่อนไปด้านบนหลังจากใช้ตำแหน่ง: แก้ไขแล้ว ขอบคุณ!
Annia Martinez

3

แล้วเรื่องนี้ล่ะ (หากคุณใช้ 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() });
    }
};

ค่อนข้างน่ากลัว แต่ใช้งานได้กับ IE 7 (ไคลเอนต์ใช้มัน) โซลูชันอื่นไม่ทำ
niki b

3

ฉันใช้showModalDialogเพื่อแสดงหน้ารองเป็นกล่องโต้ตอบโมดอล

เพื่อซ่อนแถบเลื่อนหน้าต่างหลัก:

document.body.style.overflow = "hidden";

และเมื่อปิดกล่องโต้ตอบโมดัลแสดงแถบเลื่อนหน้าต่างหลัก:

document.body.style.overflow = "scroll";

เพื่อเข้าถึงองค์ประกอบในหน้าต่างหลักจากกล่องโต้ตอบ:

parent.document.getElementById('dialog-close').click();

สำหรับทุกคนที่ค้นหาshowModalDialog : (หลังจากบรรทัดที่ 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();
});

สิ่งนี้ใช้ได้กับฉันใน React ที่ jQuery ไม่มีอยู่จริงและที่ React ไม่มีสิทธิ์เข้าถึงเพื่อจัดการสถานะของแท็กเนื้อหา
Jon

3

การยกเลิกกิจกรรมในคำตอบที่ยอมรับเป็นวิธีที่น่ากลัวในความคิดของฉัน: /

ฉันใช้position: fixed; top: -scrollTop();ด้านล่างแทน

ตัวอย่าง: https://jsfiddle.net/w9w9hthy/5/

จากโครงการป๊อปอัพ jQuery ของฉัน: 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 แนวตั้ง

หากใครมีการปรับปรุงใด ๆ ของรหัสด้านบนหน้า freeze / unfreeze แจ้งให้ฉันทราบเพื่อให้ฉันสามารถเพิ่มการปรับปรุงเหล่านั้นในโครงการของฉัน


3
var winX = null, winY = null;
window.addEventListener('scroll', function () {
    if (winX !== null && winY !== null) {
        window.scrollTo(winX, winY);
    }
});
function disableWindowScroll() {
    winX = window.scrollX;
    winY = window.scrollY;
};
function enableWindowScroll() {
    winX = null;
    winY = null;
};

1
นี่คือทางออกที่ดีที่สุดที่นี่
jfunk

@jfunk เห็นด้วยง่ายและกระชับรหัสขนาดเล็กที่สมบูรณ์แบบ ขอบคุณ
Florent Roques

2

ฉันมีปัญหาเดียวกันด้านล่างเป็นวิธีที่ฉันจัดการกับมัน

/* file.js */
var body = document.getElementsByTagName('body')[0];
//if window dont scroll
body.classList.add("no-scroll");
//if window scroll
body.classList.remove("no-scroll");

/* file.css */
.no-scroll{
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

หวังว่าความช่วยเหลือนี้


1

การสร้างคำตอบของ Cheyenne Forbes และสิ่งหนึ่งที่ฉันพบที่นี่ผ่าน fcalderan: เพียงแค่ปิดการใช้งาน scroll ไม่ซ่อนหรือไม่ และเพื่อแก้ไขปัญหาของแถบเลื่อนของ Hallodom ที่หายไป

CSS:

.preventscroll{
    position: fixed;
    overflow-y:scroll;
}

JS:

whatever.onclick = function(){
    $('body').addClass('preventscroll');
}
whatevertoclose.onclick = function(){
    $('body').removeClass('preventscroll');
}

รหัสนี้จะข้ามคุณไปด้านบนของหน้า แต่ฉันคิดว่ารหัส fcalderan มีวิธีแก้ปัญหา


1

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันต้องทำสิ่งที่คล้ายกันมากและหลังจากเวลาหาคำตอบและลองวิธีการที่แตกต่างกันฉันจบลงด้วยการใช้โซลูชันที่ง่ายมาก

ปัญหาของฉันคล้ายกันเกือบเหมือนกันความแตกต่างเพียงอย่างเดียวคือฉันไม่ต้องแสดงแถบเลื่อนจริง ๆ - ฉันต้องตรวจสอบให้แน่ใจว่าความกว้างของมันจะยังคงถูกใช้อยู่ดังนั้นความกว้างของหน้าจะไม่เปลี่ยนแปลงในขณะที่ภาพซ้อนทับปรากฏ .

เมื่อฉันเริ่มเลื่อนภาพซ้อนทับลงในหน้าจอฉันจะทำ:

$('body').addClass('stop-scrolling').css('margin-right', 8);

และหลังจากที่ฉันเลื่อนภาพซ้อนทับออกจากหน้าจอฉันก็:

$('body').removeClass('stop-scrolling').css('margin-right', 0);

สำคัญ:นี้ทำงานได้อย่างสมบูรณ์เพราะการซ้อนทับของฉันอยู่ในตำแหน่งabsolute, เมื่อright: 0pxvisible


1

วิธีที่ง่ายที่สุดคือ:

$("body").css("overflow", "hidden"); // Remove the scroll bar temporarily

วิธียกเลิก:

$("body").css("overflow", "auto");

ใช้งานง่าย แต่ข้อเสียเพียงอย่างเดียวคือ:

  • หน้าจะกระโดดไปทางซ้ายเล็กน้อยหากอยู่กึ่งกลาง (แนวนอน)

นี่เป็นเพราะแถบเลื่อนถูกลบออกและวิวพอร์ตก็กว้างขึ้นเล็กน้อย


1
ที่จะรีเซ็ตตำแหน่งการเลื่อน
Angel David Calderaro Pacciott

@AngelDavidCalderaroPacciott ไม่ตำแหน่งการเลื่อนจะยังคงความสูง / ระยะทางเท่าเดิม
Daan

@Daan มันไม่รีเซ็ตเลื่อนตำแหน่งบน Chrome
ทอม

@Tom ฉันเพิ่งตรวจสอบมันจะทำในบางโอกาสเท่านั้น (เมื่อความสูงของร่างกายไม่สัมพันธ์กับลูก ๆ ของมัน) โปรดลองเปลี่ยนbodyไปhtmlแทน
Daan

ฉันพนันว่าคุณไม่ได้ตรวจสอบวิธีการแก้ปัญหาของคุณใน Iphone เพราะoverflow:hiddenไม่ได้ทำงานในนั้น
Shuvo

1

นี่คือทางออกของฉันเพื่อหยุดการเลื่อน (ไม่มี jQuery) ฉันใช้เพื่อปิดการใช้งานการเลื่อนเมื่อเมนูด้านข้างปรากฏขึ้น

<button onClick="noscroll()" style="position:fixed; padding: 8px 16px;">Disable/Enable scroll</button>
<script>
var noscroll_var;
function noscroll(){
  if(noscroll_var){
    document.getElementsByTagName("html")[0].style.overflowY = "";
    document.body.style.paddingRight = "0";
    noscroll_var = false
  }else{
    document.getElementsByTagName("html")[0].setAttribute('style', 'overflow-y: hidden !important');
    document.body.style.paddingRight = "17px";
    noscroll_var = true
  }
}/*noscroll()*/
</script>

<!-- Just to fill the page -->
<script>
  for(var i=0; i <= 80; i++){
    document.write(i + "<hr>")
  }
</script>

ฉันใส่ 17px ของการเติมขวาเพื่อชดเชยการหายตัวไปของแถบเลื่อน แต่นี่ก็เป็นปัญหาเช่นกันส่วนใหญ่สำหรับเบราว์เซอร์มือถือ แก้ไขได้โดยการได้รับแถบความกว้างตามนี้

มารวมกันในปากกานี้



1

นี่เป็นทางออกที่ง่ายที่สุดที่ฉันได้รับ และเชื่อฉันฉันพยายามทั้งหมดอื่น ๆ และนี่คือสิ่งที่ง่ายที่สุด มันใช้งานได้ดีบนอุปกรณ์ Windowsซึ่งผลักหน้าจากด้านขวาเพื่อให้มีที่ว่างสำหรับแถบเลื่อนระบบและอุปกรณ์ IOSซึ่งไม่ต้องการพื้นที่สำหรับแถบเลื่อนในเบราว์เซอร์ ดังนั้นโดยใช้สิ่งนี้คุณไม่จำเป็นต้องเพิ่มการเติมด้านขวาเพื่อให้หน้าไม่สั่นเมื่อคุณซ่อนโอเวอร์โฟลว์ของร่างกายหรือ html ด้วย cssกับซีเอสเอ

การแก้ปัญหาค่อนข้างง่ายถ้าคุณคิดเกี่ยวกับมัน ความคิดคือการให้window.scrollTop ()ตำแหน่งที่แน่นอนเดียวกันในขณะที่เปิดป๊อปอัพ นอกจากนี้ยังเปลี่ยนตำแหน่งนั้นเมื่อปรับขนาดหน้าต่าง (เมื่อตำแหน่งการเลื่อนเปลี่ยนไปเมื่อเกิดขึ้น)

ดังนั้นที่นี่เราไป ...

แรกให้สร้างตัวแปรที่จะช่วยให้คุณทราบว่าป๊อปอัพที่เปิดอยู่และเรียกมันว่าstopWindowScroll หากเราไม่ทำเช่นนี้คุณจะได้รับข้อผิดพลาดของตัวแปรที่ไม่ได้กำหนดบนหน้าของคุณและตั้งเป็น 0 - ไม่ใช้งาน

$(document).ready(function(){
    stopWindowScroll = 0;
});

ตอนนี้ให้การเปิดฟังก์ชั่นป๊อปอัพแม่มดสามารถเป็นฟังก์ชั่นใด ๆ ในรหัสของคุณที่ก่อให้เกิดสิ่งที่ป๊อปอัพที่คุณใช้เป็นปลั๊กอินหรือกำหนดเอง ในกรณีนี้มันจะเป็นป๊อปอัปที่กำหนดเองอย่างง่ายพร้อมฟังก์ชั่นเอกสารแบบง่ายในการคลิก

$(document).on('click','.open-popup', function(){
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
});

ดังนั้นสิ่งต่อไปที่เราทำคือสร้างฟังก์ชั่นปิดป๊อปอัพซึ่งฉันทำซ้ำอีกครั้งอาจเป็นฟังก์ชั่นใด ๆ ที่คุณสร้างขึ้นแล้วหรือใช้ในปลั๊กอิน สิ่งสำคัญคือเราต้องใช้ทั้ง 2 ฟังก์ชั่นเพื่อตั้งค่าตัวแปรstopWindowScrollเป็น 1 หรือ 0 เพื่อทราบเมื่อเปิดหรือปิด

$(document).on('click','.open-popup', function(){
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
});

จากนั้นให้สร้างฟังก์ชั่น window.scroll เพื่อให้เราสามารถป้องกันการเลื่อนได้เมื่อstopWindowScroll ที่กล่าวถึงข้างต้นถูกตั้งค่าเป็น 1 - เป็น active

$(window).scroll(function(){
    if(stopWindowScroll == 1) {
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    }
});

แค่นั้นแหละ. ไม่จำเป็นต้องใช้ CSS เพื่อให้ทำงานได้ยกเว้นสไตล์ของคุณสำหรับหน้า สิ่งนี้ได้ผลเช่นเดียวกับฉันและฉันหวังว่ามันจะช่วยคุณและคนอื่น ๆ

นี่คือตัวอย่างการทำงานบน JSFiddle:

ตัวอย่าง JS Fiddle

แจ้งให้เราทราบหากสิ่งนี้ช่วยได้ ความนับถือ.


1

เก็บความยาวการเลื่อนในตัวแปรส่วนกลางและเรียกคืนเมื่อจำเป็น!

var sctollTop_length = 0;

function scroll_pause(){
  sctollTop_length = $(window).scrollTop();
  $("body").css("overflow", "hidden");
}

function scroll_resume(){
  $("body").css("overflow", "auto");
  $(window).scrollTop(sctollTop_length);
}

1

รหัสนี้จะทำงานกับChrome 56ขึ้นไป (คำตอบดั้งเดิมไม่สามารถใช้กับ Chrome ได้อีกต่อไป)

ใช้ DomUtils.enableScroll()เพื่อเปิดใช้งานการเลื่อน

ใช้DomUtils.disableScroll()เพื่อปิดการเลื่อน

class DomUtils {
  // left: 37, up: 38, right: 39, down: 40,
  // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
  static keys = { 37: 1, 38: 1, 39: 1, 40: 1 };

  static preventDefault(e) {
    e = e || window.event;
    if (e.preventDefault) e.preventDefault();
    e.returnValue = false;
  }

  static preventDefaultForScrollKeys(e) {
    if (DomUtils.keys[e.keyCode]) {
      DomUtils.preventDefault(e);
      return false;
    }
  }

  static disableScroll() {
    document.addEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Disable scrolling in Chrome
    document.addEventListener('keydown', DomUtils.preventDefaultForScrollKeys, {
      passive: false,
    });
  }

  static enableScroll() {
    document.removeEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Enable scrolling in Chrome
    document.removeEventListener(
      'keydown',
      DomUtils.preventDefaultForScrollKeys,
      {
        passive: false,
      }
    ); // Enable scrolling in Chrome
  }
}

1

เพื่อป้องกันการกระโดดนี่คือสิ่งที่ฉันใช้

export function toggleBodyScroll(disable) {
  if (!window.tempScrollTop) {
    window.tempScrollTop = window.pageYOffset; 
    // save the current position in a global variable so I can access again later

  }
  if (disable) {
    document.body.classList.add('disable-scroll');
    document.body.style.top = `-${window.tempScrollTop}px`;
  } else {
    document.body.classList.remove('disable-scroll');
    document.body.style.top = `0px`;
    window.scrollTo({top: window.tempScrollTop});
    window.tempScrollTop = 0;
  }
}

และใน CSS ของฉัน

.disable-scroll {
  height: 100%;
  overflow: hidden;
  width: 100%;
  position: fixed;
}

0

ฉันพบคำตอบนี้ในเว็บไซต์อื่น:

ปิดการใช้งานการเลื่อน:

$( ".popup").live({
    popupbeforeposition: function(event, ui) {
    $("body").on("touchmove", false);
}
});

หลังจากปิดการเลื่อนการปล่อยป๊อปอัป:

$( ".popup" ).live({
    popupafterclose: function(event, ui) {
    $("body").unbind("touchmove");
}
});

ดูเหมือนว่าจะหยุดการเลื่อนแบบสัมผัสเท่านั้น แต่การเลื่อนเมาส์, ปุ่มลูกศร, ปุ่มเลื่อนขึ้นและลง ฯลฯ จะยังคงใช้งานได้ -1
markasoftware

'กิจกรรม' เหล่านี้ใช้สำหรับการเลื่อนแบบสัมผัสเพียงแค่เปลี่ยนเหตุการณ์ใดก็ตามที่คุณต้องการ
pennstump

1
นอกจากนี้ดูเหมือนว่าจะใช้ในสถานการณ์ที่เฉพาะเจาะจงอื่น ๆ popupbeforeposition? สิ่งที่ควรจะมีไว้เพื่อ? สิ่งนี้เกี่ยวข้องกับการปิดใช้งานการเลื่อนชั่วคราว? อย่างน้อยก็ทำให้มันเกี่ยวข้องกับสถานการณ์นี้ ดูเหมือนว่าคุณจะคัดลอกสิ่งนี้โดยตรงจากเว็บไซต์
markasoftware

0

วิธีแก้ปัญหาของ galambalazs ยอดเยี่ยมมาก! มันทำงานได้อย่างสมบูรณ์แบบสำหรับฉันทั้งใน Chrome และ Firefox และอาจขยายเพื่อป้องกันเหตุการณ์เริ่มต้นจากหน้าต่างเบราว์เซอร์ สมมติว่าคุณกำลังทำแอพบนผืนผ้าใบ คุณสามารถทำได้:

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

และในแอปของคุณสมมติว่าคุณกำลังประมวลผลกิจกรรมของคุณเองเช่นเมาส์แป้นพิมพ์กิจกรรมการแตะและอื่น ๆ ... คุณสามารถปิดการใช้งานเหตุการณ์เริ่มต้นเมื่อเมาส์เข้าไปในผืนผ้าใบและเปิดใช้งานอีกครั้งเมื่อเมาส์ ออกไป:

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

0

ฉันมีปัญหาแอนิเมชั่นที่คล้ายกันบนหน้าจอมือถือ แต่ไม่ได้อยู่ในแล็ปท็อปเมื่อพยายามทำให้ภาพเคลื่อนไหว div โดยใช้คำสั่งภาพเคลื่อนไหวของ jquery ดังนั้นฉันจึงตัดสินใจใช้ตัวจับเวลาที่คืนค่าตำแหน่งการเลื่อนของหน้าต่างบ่อยครั้งเพื่อที่ว่าด้วยตาเปล่าเอกสารจะปรากฏเป็นแบบคงที่ โซลูชันนี้ทำงานอย่างสมบูรณ์แบบบนอุปกรณ์พกพาหน้าจอขนาดเล็กเช่น Samsung Galaxy-2 หรือ iphone-5

ตรรกะหลักของวิธีการนี้ : ตัวจับเวลาในการตั้งค่าตำแหน่งเลื่อนของหน้าต่างไปยังตำแหน่งเลื่อนเริ่มต้นก่อนคำสั่ง jQuery animate และเมื่อภาพเคลื่อนไหวเสร็จสิ้นเราจำเป็นต้องล้างตัวจับเวลานี้ (original scroll positionเป็นตำแหน่งก่อนที่จะเริ่มเคลื่อนไหว)

ฉันพบความประหลาดใจที่น่าพอใจว่าเอกสารปรากฏขึ้นจริงในช่วงระยะเวลาของภาพเคลื่อนไหวหากช่วงเวลาตัวนับ1 millisecondเป็นสิ่งที่ฉันต้องการ

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

โซลูชันอื่นที่ใช้งานได้ : ตามคำตอบของโมฮัมหมัดอานินี่ภายใต้โพสต์นี้เพื่อเปิด / ปิดการเลื่อนฉันพบว่ามีการแก้ไขโค้ดดังต่อไปนี้

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

0

วิธีแก้ปัญหาง่ายๆที่ใช้งานได้สำหรับฉัน (ปิดการใช้งานการเลื่อนหน้าต่างชั่วคราว)

อิงตามซอนี้: 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;
 }

ตอนนี้เมื่อคุณลบโมดอลอย่าลืมลบคลาส noscroll บนแท็ก html:

$('html').toggleClass('noscroll');
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.