Javascript 当窗口垂直滚动条出现时检测

Javascript 当窗口垂直滚动条出现时检测,javascript,jquery,resize,scrollbar,Javascript,Jquery,Resize,Scrollbar,是否有一个简单可靠的解决方案来检测窗口垂直滚动条的出现/消失 当JavaScriptDOM操作后页面变高到足以显示滚动条时,不会触发window.onresize 在这篇非常类似的文章中,我描述了如何检测滚动条是否存在,但我需要知道它的确切出现时间。很抱歉,让我死而复生,但我刚刚遇到了这个限制,并提出了我自己的解决方案。这有点老套,但还是跟着我 其想法是在页面上添加一个100%宽度的不可见iframe,并在其内部窗口上侦听调整大小事件。这些事件不仅会拾取外部窗口大小的更改,还会在外部窗口中添加或

是否有一个简单可靠的解决方案来检测窗口垂直滚动条的出现/消失

当JavaScriptDOM操作后页面变高到足以显示滚动条时,不会触发
window.onresize


在这篇非常类似的文章中,我描述了如何检测滚动条是否存在,但我需要知道它的确切出现时间。

很抱歉,让我死而复生,但我刚刚遇到了这个限制,并提出了我自己的解决方案。这有点老套,但还是跟着我

其想法是在页面上添加一个100%宽度的不可见iframe,并在其内部窗口上侦听调整大小事件。这些事件不仅会拾取外部窗口大小的更改,还会在外部窗口中添加或删除滚动条时拾取更改

它会触发一个常规的窗口大小调整事件,所以如果您已经在侦听窗口大小调整,则不需要额外的代码

在IE9和Chrome/Firefox最新版本中测试-可能在旧版IEs中工作,但我的项目不支持这些,所以我没有尝试过


根据Panda的回答,他想出了这个jquery的东西

$('<iframe id="scrollbar-listener"/>').css({
    'position'      : 'fixed',
'width'         : '100%',
'height'        : 0, 
'bottom'        : 0,
'border'        : 0,
'background-color'  : 'transparent'
}).on('load',function() {
    var vsb     = (document.body.scrollHeight > document.body.clientHeight);
    var timer   = null;
    this.contentWindow.addEventListener('resize', function() {
        clearTimeout(timer);
        timer = setTimeout(function() {
            var vsbnew = (document.body.scrollHeight > document.body.clientHeight);
            if (vsbnew) {
                if (!vsb) {
                    $(top.window).trigger('scrollbar',[true]);
                    vsb=true;
                }
            } else {
                if (vsb) {
                    $(top.window).trigger('scrollbar',[false]);
                    vsb=false;
                }
            }
        }, 100);
    });
}).appendTo('body');
$('').css({
'位置':'固定',
“宽度”:“100%”,
“高度”:0,
“底部”:0,
“边框”:0,
“背景色”:“透明”
}).on('load',function()){
var vsb=(document.body.scrollHeight>document.body.clientHeight);
var定时器=null;
this.contentWindow.addEventListener('resize',function()){
清除超时(计时器);
计时器=设置超时(函数(){
var vsbnew=(document.body.scrollHeight>document.body.clientHeight);
if(vsbnew){
如果(!vsb){
$(top.window).trigger('scrollbar',[true]);
vsb=真;
}
}否则{
中频(vsb){
$(top.window).trigger('scrollbar',[false]);
vsb=假;
}
}
}, 100);
});
}).附于(“主体”);
这将触发窗口上的“滚动条”事件(如果出现/消失)


至少可以在chrome/mac上使用。现在,有人扩展它来检测水平滚动条:-)

动态检测浏览器垂直滚动条事件 正在将window.innerWidth与getBoundingClientRect()进行比较 使用Javascript创建一个DIV元素。使用最新版本进行测试
IE FF铬合金。请参阅文档

如果您使用的是AngularJS,则可以使用指令来检测宽度何时更改(假设出现/消失的滚动条是垂直的):

这将在根作用域上激发一个事件,其他指令或控制器可以侦听该事件

手表由angular digest循环触发,因此这取决于angular是否加载/删除了导致滚动条出现/消失的额外内容。

通过使用
ResizeObserver
检查可能占用滚动条的元素大小的变化及其内容大小的变化,可以检测滚动条可见性的变化

根本原因 我开始用
方法实现一个解决方案,但很快发现要实现一个完整的解决方案,需要打破应用程序视图之间的关注点分离。我有一个父视图,它需要知道子视图何时获得垂直滚动条。(我不关心水平滚动条。)我有两种情况可能会影响垂直滚动条的可见性:

  • 父视图的大小已调整。这由用户直接控制

  • 子视图的内容变大或变小。这是由用户间接控制的。子视图将显示搜索结果。结果的数量和类型决定了子视图的大小

  • 我发现如果我使用
    ,我将不得不修改子视图以支持父视图的需要。我希望孩子不包含纯粹是家长关心的东西的代码。使用我在这里描述的解决方案,只需要修改父视图

    因此,在寻找更好的解决方案时,我找到了Daniel Herr。他建议使用
    ResizeObserver
    来检测div的维度何时发生变化
    ResizeObserver
    还不能在浏览器中以本机方式提供,但在本机支持不可用的情况下,我会使用强大的ponyfill/polyfill来提供支持。(以下是针对
    ResizeObserver
    的示例)

    概念证明 我在它的ponyfill模式下使用。这样,全球环境就不会受到影响。此实现依赖于
    window.requestAnimationFrame
    ,对于不支持
    window.requestAnimationFrame
    的平台,将依赖于
    setTimeout
    。看着“我能用…?”上的文字,我看到的并没有困扰我。YMMV

    我有一个活的。关键是监听可以接受滚动条的DOM元素(id为
    容器的元素,绿色)的大小变化,以及监听可能需要滚动的内容(id为
    内容的元素)的大小变化。概念验证使用
    interact.js
    来管理一个resizer元素(id
    resizer
    ,蓝色),该元素允许调整容器的大小。如果拖动大小调整器的右下角,它将同时调整大小调整器和容器的大小。这两个按钮允许模拟容器显示的内容大小的变化

    我在目前处于预发布阶段的代码中使用此方法,这意味着它通过了多个浏览器上的测试,并且正在由涉众进行评估,但尚未投入生产

    HTML:

    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="interact.js@*" data-semver="1.0.26" src="//rawgit.com/taye/interact.js/v1.0.26/interact.js"></script>
      <script src="//rawgit.com/que-etc/resize-observer-polyfill/master/dist/ResizeObserver.global.js"></script>
      <link rel="stylesheet" href="style.css" />
    </head>
    
    <body>
      <div id="resizer">
        <div id="container">
          <ul id="content">
            <li>Something</li>
          </ul>
        </div>
      </div>
      <button id="add">Add to content</button>
      <button id="remove">Remove from content</button>
      <p>Scroll bar is: <span id="visibility"></span></p>
      <ul id="event-log"></ul>
      <script src="script.js"></script>
    </body>
    
    </html>
    
    这一切都是关于何时需要确定滚动条的可见性

    OP提到了一个时间“在JavaScript DOM manipula之后”
    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="interact.js@*" data-semver="1.0.26" src="//rawgit.com/taye/interact.js/v1.0.26/interact.js"></script>
      <script src="//rawgit.com/que-etc/resize-observer-polyfill/master/dist/ResizeObserver.global.js"></script>
      <link rel="stylesheet" href="style.css" />
    </head>
    
    <body>
      <div id="resizer">
        <div id="container">
          <ul id="content">
            <li>Something</li>
          </ul>
        </div>
      </div>
      <button id="add">Add to content</button>
      <button id="remove">Remove from content</button>
      <p>Scroll bar is: <span id="visibility"></span></p>
      <ul id="event-log"></ul>
      <script src="script.js"></script>
    </body>
    
    </html>
    
    var container = document.getElementById("container");
    var resizer = document.getElementById("resizer");
    interact(resizer)
      .resizable({
        restrict: {
          restriction: {
            left: 0,
            top: 0,
            right: window.innerWidth - 10,
            bottom: window.innerHeight - 10
          }
        }
      })
      .on('resizemove', function(event) {
        var target = resizer;
    
        var rect = target.getBoundingClientRect();
    
        var width = rect.width + event.dx;
        var height = rect.height + event.dy;
        target.style.width = width + 'px';
        target.style.height = height + 'px';
      });
    
    var content = document.getElementById("content");
    var add = document.getElementById("add");
    add.addEventListener("click", function() {
      content.insertAdjacentHTML("beforeend", "<li>Foo</li>");
    });
    
    var remove = document.getElementById("remove");
    remove.addEventListener("click", function() {
      content.removeChild(content.lastChild);
    });
    
    // Here is the code that pertains to the scrollbar visibility
    
    var log = document.getElementById("event-log");
    content.addEventListener("scrollbar", function () {
      log.insertAdjacentHTML("beforeend", "<li>Scrollbar changed!</li>");
    });
    
    var visiblity = document.getElementById("visibility");
    var previouslyVisible;
    function refreshVisibility() {
      var visible = container.scrollHeight > container.clientHeight;
      visibility.textContent = visible ? "visible" : "not visible";
      if (visible !== previouslyVisible) {
        content.dispatchEvent(new Event("scrollbar"));
      }
      previouslyVisible = visible;
    }
    // refreshVisibility();
    
    
    var ro = new ResizeObserver(refreshVisibility);
    ro.observe(container);
    ro.observe(content);
    
    * {
      box-sizing: border-box;
    }
    
    #container {
      position: relative;
      top: 10%;
      left: 10%;
      height: 80%;
      width: 80%;
      background: green;
      overflow: auto;
    }
    
    #resizer {
      background: blue;
      height: 200px;
      width: 200px;
    }