Jquery在滚动时滞后

时间:2017-05-18 21:47:56

标签: javascript jquery html css

当桌子水平滚动时,我计算一些绝对元素的左侧位置。它在chrome中效果很好,但在safari和firefox中,绝对元素滞后并导致滚动不稳定。有什么方法可以提高性能,以便在所有三个浏览器中滚动顺畅吗?

这是我在angular1指令中的函数:



angular.module('app.doubleHorizontalScrollDirective', []).directive('doubleHorizontalScroll', ['$timeout',
  function($timeout) {

    return {
      restrict: 'A',
      transclude: true,
      scope: {
        topScrollDisplay: '=', // if equals 'hide' will not display scroll bars even if there is something to scroll; otherwise show them only when content overflows display area
        bottomScrollDisplay: '=',
        controlledScroll: '@',
        controlledOffsetLeft: '@'
      },

      // HTML template
      template: '' +
        '<div>' +
        ' <div style="overflow-y:hidden; height: 24px;" data-ng-style="{\'margin-bottom\':hasHorizontalScrollbar?\'12px\':\'0px\', \'margin-top\':hasHorizontalScrollbar?\'12px\':\'0px\'}">' +
        '  <div style="overflow-y:hidden;position:relative;top:-1px;height: 25px" ' +
        'data-ng-style="{\'overflow-x\': topScrollDisplay?topScrollDisplay:\'auto\'}">' +
        '   <div style="height: 25px" data-ng-style="{width:wrapper2scrollWidth}"></div>' +
        '  </div>' +
        ' </div>' +
        ' <div style="overflow-y: auto; margin-right: -15px" data-ng-style="{\'overflow-x\': bottomScrollDisplay?bottomScrollDisplay:\'auto\'}">' +
        '  <div data-ng-transclude></div>' +
        ' </div>' +
        '</div>',

      link: function($scope, iElm, iAttrs, controller) {

        let adjustColumnPositions = (scrollPosition) => {
          $($scope.controlledScroll).scrollLeft(scrollPosition);
          $($scope.controlledOffsetLeft).css({
            'left': scrollPosition
          });

          $('.video-analysis__default_table__item__panel__body--index.fixed-left-index').css({
            'left': scrollPosition
          });

          $('.video-analysis__default_table__item__panel__body--checkbox.fixed-left-checkbox').css({
            'left': scrollPosition + 40
          });

          $('.video-analysis__default_table__item__panel__body--star.fixed-left-star').css({
            'left': scrollPosition + 73
          });

          $('.video-analysis__default_table__item__panel__body--plus.fixed-right').css({
            'right': (0 - scrollPosition)
          });
        };

        // scroll width of the wrapper2 div, width of div inside wrapper1 will be set to the same value
        $scope.wrapper2scrollWidth = '0px';
        $scope.hasHorizontalScrollbar = false;

        // angular.element representation od the root <div> of this directive
        let rootDiv = iElm.children().eq(0);

        // angular.element object for the first div in the root
        // <div style="overflow-y:hidden;position:relative;top:-1px;height: 25px" data-ng-style="{\'overflow-x\':doubleScrollBarHorizontal==\'always\'?\'scroll\':\'auto\'}">'
        // the 'virtual' top scroll bar will be here
        let wrapper1 = rootDiv.children().eq(0).children().eq(0);

        // angular.element object for the second div in the root
        // <div data-ng-style="{\'overflow-x\': doubleScrollBarHorizontal == \'always\' ? \'scroll\' : \'auto\'}">
        // the 'real' bottom scroll bar will be here
        let wrapper2 = rootDiv.children().eq(1);

        //let controlledScroll = $($scope.controlledScroll).

        // if scrolling one ruler, scroll also the other one

        wrapper1.on('scroll', function() {
          wrapper2.scrollLeft(wrapper1.scrollLeft());
          adjustColumnPositions(wrapper1.scrollLeft());
        });

        wrapper2.on('scroll', function() {
          wrapper1.scrollLeft(wrapper2.scrollLeft());
          adjustColumnPositions(wrapper2.scrollLeft());
        });

        let firstTime = true;

        // watch for a change of the width (e.g. transcluded content changed and so changed its width)
        $scope.$watch(function() {
          return ($scope.wrapper2scrollWidth = wrapper2[0].scrollWidth + 'px');
        }, function(newValue, oldValue) {
          // run $apply one more time so the scroll bars are in sync
          // $timeout to run it on next $digest cycle, otherwise angular will complain of '$digest already in process'
          //$timeout(function() {
          $scope.hasHorizontalScrollbar = wrapper2[0].scrollWidth > wrapper2[0].clientWidth;
          //$scope.$apply();

          // first time after recompiled and width set (width set in $apply())
          if (firstTime) {
            // initial values for scroll position - zero if this directive is compiled very first time or if no id provided, otherwise use last scroll position (from service)
            wrapper1.scrollLeft(0);
            wrapper2.scrollLeft(0);
            firstTime = false;
          }

          //}, 500);
        });

        /*$scope.$watch(function() { // adjusts the margin of the header depending on width of vertical scrollbar
          return wrapper2[0].offsetWidth
        }, function(newValue, oldValue) {
          $($scope.controlledScroll).css({
            'margin-right': (wrapper2[0].offsetWidth - wrapper2[0].clientWidth)
          });
        });*/
      }
    };
  }
]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<table>
  <tr class="clickable" ng-click="playClip(item)" ng-mouseenter="color = 'clip-hover'" ng-mouseleave="color = ''">
    <td class="video-analysis__default_table__item__panel__body--index fixed-left-index">
      <div class="relative" ng-bind="$index + 1" ng-class="color"></div>
    </td>

    <td class="video-analysis__default_table__item__panel__body--checkbox fixed-left-checkbox">
      <div class="relative" ng-class="color">
        <input type="checkbox" ng-click="toggleClipCollection(item); $event.stopPropagation();" ng-checked="is_InClipCollection(item)">
      </div>
    </td>

    <td class="video-analysis__default_table__item__panel__body--star fixed-left-star">
      <div class="relative" ng-class="color">
        <i class="fa fa-favorite" ng-click="toggleStarredClip(item); $event.stopPropagation();" ng-class="{active: isStarredClip(item)}">
                  </i>
      </div>
    </td>

    <td ng-repeat="column in currentHeaders" ng-class="'video-analysis__default_table__item__panel__body--' + column.class +' '+color">
      <span ng-bind="getClipDatum(column.sorting_column, item)"></span>
    </td>

    <td ng-show="emptySpaceExists()" ng-class="color" ng-style="{'width' : remainingWidth + 'px'}">
    </td>

    <td class="video-analysis__default_table__item__panel__body--plus fixed-right" ng-click="is_collapsed = !is_collapsed; $event.stopPropagation();">
      <div class="relative" ng-class="color">
        <span class="fa fa-plus-square fa-2x" ng-show="is_collapsed"></span>
        <span class="fa fa-minus-square-o fa-2x" ng-hide="is_collapsed"></span>
      </div>
    </td>
  </tr>
</table>
&#13;
&#13;
&#13;

0 个答案:

没有答案