web-dev-qa-db-ja.com

Angularjs:divのスクロールバーの下部にスクロールが到達したときにイベントをトリガーする方法

スクロールバーが最後に達したときにイベントをトリガーしようとしています。私はこれを見つけました この例 。これが私のコードです。問題は、loadmore()をまったく呼び出さないことです。コンソールの状態の値は次のとおりです。

848
899
in scroll
881
899
in scroll
892
899
in scroll
897
899
in scroll
900
899

Ifステートメントには決して行かないようです!奇妙な部分は、検査要素でデバッグするとイベントがトリガーされることです。 .....私の指示:

directive('scrolly', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var raw = element[0];
            console.log('loading directive');
            element.bind('scroll', function () {
                console.log('in scroll');
                console.log(raw.scrollTop + raw.offsetHeight);
                console.log(raw.scrollHeight);
                if (raw.scrollTop + raw.offsetHeight == raw.scrollHeight) { //at the bottom
                    scope.$apply(attrs.scrolly);
                }
            })
        }
    }
24
Sara

等しいかどうかを確認する代わりに、ifステートメントの左側が右側よりも大きいかどうかを確認してください。スクロールバーが下部にあるためです。

raw.scrollTop + raw.offsetHeight > raw.scrollHeight

動作する jsfiddle です。

29

あなたは私にいくつかの良いヒントを与えました...この投稿を偶然見つけた他の人のための完全な実例がここにあります:

JS:

app.controller("controller", function ($scope) {
    $scope.test = function () {
        alert("hello!");
    }
}

HTML:

<div class="br-section1" on-scroll-to-bottom="test()">
</div>

アプリディレクティブ:

app.directive('onScrollToBottom', function ($document) {
    //This function will fire an event when the container/document is scrolled to the bottom of the page
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {

            var doc = angular.element($document)[0].body;

            $document.bind("scroll", function () {

                //console.log('in scroll');
                //console.log("scrollTop + offsetHeight:" + (doc.scrollTop + doc.offsetHeight));
                //console.log("scrollHeight: " + doc.scrollHeight);

                if (doc.scrollTop + doc.offsetHeight >= doc.scrollHeight) {
                    //run the event that was passed through
                    scope.$apply(attrs.onScrollToBottom);
                }
            });
        }
    };
});
10
Mark G

私はこれを行うのに役立つスニペットを探していましたが、価値のあるものを見つけることができなかったので、これを行うためのこの非常に使いやすいディレクティブを思い付きました

'use strict';
// Tested with Angular 1.3, 1.4.8
angular.module('scrollToEnd', [])
  /**
   * @ngdoc directive
   * @name scrollToEnd:scrollToEnd
   * @scope
   * @restrict A
   *
   * @description
   * Supply a handler to be called when this element is scrolled all the way to any extreme.
   * The callback must have the following signature:
   * void function (direction:'top'|'bottom'|'left'|'right')
   * If the `bindToWindow` attribute is truthy, the callback will be issued for the window
   * instead of the element that the directive is on.
   *
   * Example usage:
   * `<div scroll-to-end="scrollToEndWindow" bind-to-window="true">`
   * This will call the controller's `scrollToEndWindow` function whenever the window reaches
   * the edges when scrolling. If the div itself is a scrollable element for which the
   * handler should be called instead, remove the bind-to-window attribute entirely.
   *
   * @param {function}  emScrollToEnd   Callback to be invoked
   * @param {boolean}       bindToWindow        Bind to the window instead of the element
   *
   */
  .directive('scrollToEnd', function ($window) {
    // Get the specified element's computed style (height, padding, etc.) in integer form
    function getStyleInt(elem, prop) {
      try {
        return parseInt(window.getComputedStyle(elem, null).getPropertyValue(prop), 10);
      } catch (e) {
        return parseInt(elem.currentStyle[prop], 10);
      }
    }

    // Get the 'innerHeight' equivalent for a non-window element, including padding
    function getElementDimension(elem, prop) {
      switch (prop) {
        case 'width':
          return getStyleInt(elem, 'width') +
          getStyleInt(elem, 'padding-left') +
          getStyleInt(elem, 'padding-right');
        case 'height':
          return getStyleInt(elem, 'height') +
          getStyleInt(elem, 'padding-top') +
          getStyleInt(elem, 'padding-bottom');
        /*default:
          return null;*/
      }
    }
    return {
      restrict: 'A',
      scope: {
        callback: '=scrollToEnd'
      },
      link: function (scope, elem, attr) {
        var callback = scope.callback || function () {};
        var boundToWindow = attr.bindToWindow;
        var body = document.body;
        var html = document.documentElement;
        var boundElement = boundToWindow ? angular.element($window) : elem;
        var oldScrollX = 0;
        var oldScrollY = 0;
        var handleScroll = function () {
          // Dimensions of the content, including everything scrollable
          var contentWidth;
          var contentHeight;
          // The dimensions of the container with the scrolling, only the visible part
          var viewportWidth;
          var viewportHeight;
          // The offset of how much the user has scrolled
          var scrollX;
          var scrollY;

          if (boundToWindow) {
            // Window binding case - Populate Dimensions
            contentWidth = Math.max(
              body.scrollWidth,
              body.offsetWidth,
              html.clientWidth,
              html.scrollWidth,
              html.offsetWidth
            );
            contentHeight = Math.max(
              body.scrollHeight,
              body.offsetHeight,
              html.clientHeight,
              html.scrollHeight,
              html.offsetHeight
            );
            viewportWidth = window.innerWidth;
            viewportHeight = window.innerHeight;
            scrollX = (window.pageXOffset || html.scrollLeft) - (html.clientLeft || 0);
            scrollY = (window.pageYOffset || html.scrollTop) - (html.clientTop || 0);
          } else {
            // DOM element case - Populate Dimensions
            var domElement = boundElement[0];
            contentWidth = domElement.scrollWidth;
            contentHeight = domElement.scrollHeight;
            viewportWidth = getElementDimension(domElement, 'width');
            viewportHeight = getElementDimension(domElement, 'height');
            scrollX = domElement.scrollLeft;
            scrollY = domElement.scrollTop;
          }

          var scrollWasInXDirection = oldScrollX !== scrollX;
          var scrollWasInYDirection = oldScrollY !== scrollY;
          oldScrollX = scrollX;
          oldScrollY = scrollY;

          if (scrollWasInYDirection && scrollY === 0) {
            callback('top');
          } else if (scrollWasInYDirection && scrollY === contentHeight - viewportHeight) {
            callback('bottom');
          } else if (scrollWasInXDirection && scrollX === 0) {
            callback('left');
          } else if (scrollWasInXDirection && scrollX === contentWidth - viewportWidth) {
            callback('right');
          }
        };
        boundElement.bind('scroll', handleScroll);
        // Unbind the event when scope is destroyed
        scope.$on('$destroy', function () {
          boundElement.unbind('scroll', handleScroll);
        });
      }
    };
  });

https://Gist.github.com/podrezo/f80f35d6d0655f4d550cac4747c110ff

これを試すjsfiddleを次に示します。

https://jsfiddle.net/va4x5r26/2/

Angular 1.3および1.4.8で動作し、IE10およびChrome 55。

5
Petro Podrezo

ブラウザのスクロールバーが下に達したら、イベントを発生させる必要があります。以下のコードは、Angular 6。

 import { HostListener } from '@angular/core';
     @HostListener('window:scroll', ['$event'])
      onScroll(): void {
        if ((window.innerHeight + window.scrollY) >= (document.documentElement.scrollHeight - 1)) {
          // Place your code here
        }
      }
0
Indradeep