Прокрутка дочернего div прокручивает окно, как мне это остановить?


У меня есть div, с полосой прокрутки, когда он достигает конца, моя страница начинает прокрутку. Есть в любом случае я могу остановить это поведение ?

13 83

13 ответов:

вы можете отключить прокрутку всей страницы, делая что-то вроде этого:

<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>

нашел решение.

http://jsbin.com/itajok

это то, что мне нужно.

и этот код.

http://jsbin.com/itajok/edit#javascript, html

использует плагин jQuery.


обновление из-за уведомления об устаревании

С jquery-mousewheel:

старое поведение добавления трех аргументов (delta,deltaX и deltaY) в обработчик события является теперь устаревшим и будет удален в более поздних выпуск.

затем, event.deltaY теперь необходимо использовать:

var toolbox = $('#toolbox'),
    height = toolbox.height(),
    scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
  var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
  return !blockScrolling;
});

демо

выбранное решение является произведением искусства. Думал, что это было достойно плагина....

$.fn.scrollGuard = function() {
    return this
        .on( 'wheel', function ( e ) {
            var event = e.originalEvent;
            var d = event.wheelDelta || -event.detail;
            this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
            e.preventDefault();
        });
};    

Это было постоянное неудобство для меня, и это решение настолько чисто по сравнению с другими хаки, которые я видел. Любопытно узнать, как больше о том, как это работает и насколько широко это будет поддержано, но ура Дживану и тому, кто изначально придумал это. Кстати, сайте StackOverflow редактор должен ответить на это!

обновление

Я считаю, что это лучше в том, что он вообще не пытается манипулировать DOM, только предотвращает пузырение условно...

$.fn.scrollGuard2 = function() {
  return this
    .on( 'wheel', function ( e ) {
      var $this = $(this);
      if (e.originalEvent.deltaY < 0) {
        /* scrolling up */
        return ($this.scrollTop() > 0);
      } else {
        /* scrolling down */
        return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
      }
    })
  ;
};    

отлично работает в chrome и гораздо проще, чем другие решения... дайте мне знать, как это происходит в других местах...

скрипка

вы можете использовать событие наведения курсора мыши на div, чтобы отключить полосу прокрутки тела, а затем событие mouseout, чтобы активировать его снова?

например HTML

<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
    content
</div>

а потом javascript вот так:

var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
    body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
    body.style.overflowY = 'auto';
}

Если я правильно понимаю ваш вопрос, то вы хотите предотвратить прокрутку основного контента, когда мышь находится над div (скажем, боковой панелью). Для этого боковая панель может не быть дочерним элементом контейнера прокрутки основного содержимого (который был окном браузера), чтобы предотвратить появление события прокрутки до его родителя.

это, возможно, требует некоторых изменений разметки следующим образом:

<div id="wrapper"> 
    <div id="content"> 
    </div> 
</div> 
<div id="sidebar"> 
</div> 

смотрите, он работает в этот пример скрипка и сравните это с этот пример скрипку который имеет немного другое поведение мыши на боковой панели.

см. также прокрутите только один конкретный div с главной полосой прокрутки браузера.

Я написал решение этой проблемы

  var div;
  div = document.getElementsByClassName('selector')[0];

  div.addEventListener('mousewheel', function(e) {
    if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
      e.preventDefault();
      div.scrollTop = div.scrollHeight;
    } else if (div.scrollTop + e.deltaY <= 0) {
      e.preventDefault();
      div.scrollTop = 0;
    }
  }, false);

вот кросс-браузер способ сделать это на оси Y, он работает на рабочем столе и мобильных устройствах. Протестировано на OSX и iOS.

var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var deltaY = event.deltaY;
    if ( (scrollTop === maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
});

scrollArea.addEventListener("touchstart", function(event) {
    this.previousClientY = event.touches[0].clientY;
});

scrollArea.addEventListener("touchmove", function(event) {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var currentClientY = event.touches[0].clientY;
    var deltaY = this.previousClientY - currentClientY;
    if ( (scrollTop === maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
    this.previousClientY = currentClientY;
});

вы можете отключить прокрутку всей страницы, сделав что-то вроде этого, но отобразить полосу прокрутки!

<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
  var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
  var scrollTop = this.scrollTop;
  if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
    e.preventDefault();
  }
});

это отключает прокрутку в окне при вводе элемента селектора. работает как шарм.

elements = $(".selector");

elements.on('mouseenter', function() {
    window.currentScrollTop = $(window).scrollTop();
    window.currentScrollLeft = $(window).scrollTop();
    $(window).on("scroll.prevent", function() {
        $(window).scrollTop(window.currentScrollTop);
        $(window).scrollLeft(window.currentScrollLeft);
    });
});

elements.on('mouseleave', function() {
    $(window).off("scroll.prevent");
});

основываясь на ответе ceed, вот версия, которая позволяет вложить защищенные элементы прокрутки. Только элемент, на который наведена мышь, будет прокручиваться, и он прокручивается довольно плавно. Эта версия также является повторным участником. Он может быть использован несколько раз на одном элементе и будет правильно удалить и переустановить обработчики.

jQuery.fn.scrollGuard = function() {
    this
        .addClass('scroll-guarding')
        .off('.scrollGuard').on('mouseenter.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g[0].myCst = $g.scrollTop();
            $g[0].myCsl = $g.scrollLeft();
            $g.off("scroll.prevent").on("scroll.prevent", function() {
                $g.scrollTop($g[0].myCst);
                $g.scrollLeft($g[0].myCsl);
            });
        })
        .on('mouseleave.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g.off("scroll.prevent");
        });
};

один простой способ использования-добавить класс, например scroll-guard, ко всем элементам на странице, которые вы разрешаете прокручивать. Тогда используйте $('.scroll-guard').scrollGuard() для охраны их.

Если вы применяете overflow: hidden стиль он должен уйти

edit: на самом деле я прочитал Ваш вопрос неправильно, что будет только скрыть полосу прокрутки, но я не думаю, что это то, что вы ищете.

Я не мог получить ни одного из ответов для работы в Chrome и Firefox, поэтому я придумал это объединение:

$someElement.on('mousewheel DOMMouseScroll', scrollProtection);

function scrollProtection(event) {
    var $this = $(this);
    event = event.originalEvent;
    var direction = (event.wheelDelta * -1) || (event.detail);
    if (direction < 0) {
        if ($this.scrollTop() <= 0) {
            return false;
        }
    } else {
        if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
            return false;
        }
    }
}