Как предоставить динамическое (вычисляемое) свойство CSS - PullRequest
0 голосов
/ 07 ноября 2018

Я работаю над задачей, в которой каждый раз, когда пользователь прокручивает или изменяет размер экрана, я хотел бы пересчитать свойства CSS для элемента.

Допустим, я хочу включить индикатор выполнения и отчет о ходе выполнения отображаются на основе позиции прокрутки в окне

<div class='progress-bar-wrap'>
   <div class='progress-bar-progress'></div>
</div>

function updateScrollProgress () {
   this.progressIndicator.css('width', this.calculateProgressBarWidth() + 'px');
}

Я пытался зацепить события прокрутки и изменить их размер, но это, похоже, имеет запаздывающий эффект.

window.on('scroll', updateScrollProgress)
window.on('resize', updateScrollProgress)

Я попытался в прокрутке и изменить размер обработчиков событий для requestAnimationFrame

window.on('scroll', function(){window.requestAnimationFrame( updateScrollProgress))
window.on('resize', function(){window.requestAnimationFrame( updateScrollProgress))

И испытал огромное улучшение в большинстве браузеров, однако иногда он все еще отстает.

Я пытался запросить другой кадр, когда из обработчика requestAnimationFrame:

function updateScrollProgress () {
   window.requestAnimationFrame( updateScrollProgress)
   this.progressIndicator.css('width', this.calculateProgressBarWidth() + 'px');
}

Это полностью устраняет эффект задержки, но приводит к стоимости бесконечного цикла вызовов этого метода, даже когда не требуется никаких пересчетов.

Есть ли способ перехватить обработчик непосредственно перед тем, как браузер решит нарисовать элемент (ы), чтобы я мог предоставить / установить эти "динамические" значения css для свойства?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Оберните вашу функцию события через функцию debounce:

Больше информации о функциях debounce здесь:

https://davidwalsh.name/javascript-debounce-function

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

var myEfficientFn = debounce(function() {
  // All the taxing stuff you do
}, 250);

window.addEventListener('resize', myEfficientFn);
0 голосов
/ 07 ноября 2018

Что вы делаете, когда используете requestAnimationFrame. Если вы избавились от лага, используя его, неясно, почему вы говорите, что функция работает «слишком часто». Обычно в такого рода контексте «слишком часто» означает «вызывает задержку» (слишком частый запуск и замедление работы). Если нет, то ...?

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

В любом случае, requestAnimationFrame является, по крайней мере, на данный момент, подходящим инструментом для задания «незадолго до того, как браузер отобразит фрейм».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...