当桌子水平滚动时,我计算一些绝对元素的左侧位置。它在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;