setTimeout() тормозит браузер

365
10 сентября 2017, 03:01

Перед вами код, который при загрузке страницы рубит нужный текст на отдельные символы, а при вызове функции textAnimate() каждой букве которая теперь является отдельный элементом присвоится класс в котором прописана анимация. Суть проблемы такова в Хроме и в опере все почти норм, а в мазиле вообще капец, теперь конкретней, когда вызывается textAnimate(), она должна успеть присвоить всем элементам (то есть буквам), нужный класс примерно за 600ms с маленьким хвостиком так как какое то время еще потеряется на само выполнение, которое на любом из перечисленных браузеров получается примерно 150ms. Но вот проблема в том что такая общая цифра 150ms получается только если не использовать setTimeout() а в место него каждый раз без ожидания вызывать showLetter(), тогда вся операция проходит за 100-150ms и все буквы получают класс фактически одновременно, и в таком случае нужного эффекта анимации уже нет, а когда использую setTimeout()даже с нулевым значением в качестве задержки время выполнения в хроме и опере примерно 1100ms, плохо ну ещё куда не шло, но в мазиле около 2500ms, а при таком раскладе анимашка уже совсем не та(. Прошу у знающих людей совета, как выйти на нужное время, а также почему так происходит что не так с setTimeout(). Спасибо за ваши ответы.

`        var timeout = 600;
      (function(){
        var
          descriptions = $('.slider__image-description'),
          titles = descriptions.find('h2'),
          technologists = descriptions.find('p');
          //функция подготовит текст к анимации порубает на отдельные буквы все что надо
        function fraction(e){
          e.forEach(function(item){
            item.each(function(){
              var that = $(this);
              var string = that.text();
              that.html(string.replace(/./g, '<span class="letter">$&</span>'));
            });
          }); 
          return;
        }
        fraction([titles, technologists]);
      })();
      function textAnimate(that){
        var
          letterList = that.find('.letter'),
          listLength = letterList.length,
          i = 0;
        (function showLetter(){
          var currentLetter = $(letterList[i]).html();
         //если это пробел зададим ему фиксированную ширину иначе потом он сплющиться 
          if (currentLetter === ' ') {
            var letterWidth = $(letterList[i]).width();
          //если ширина пробела = 0, значит это конец строки и нужно вставить елемент переноса строки
            if (letterWidth == 0) {
              $(letterList[i]).after('<br>');
            }
            $(letterList[i]).width(letterWidth);
          }else{
            //добавим клас с анимацией
            $(letterList[i]).addClass('showLetter');
          }
          i++;
          setTimeout(function(){
            if (i < listLength) {
              showLetter();
            } 
          }, timeout/listLength);
        })();
      }`
Answer 1

Попробуйте так, метод построен на css анимации, где setTimeout используется лишь для того, что бы задать определенный класс контейнеру который начнет эту анимацию:

$(function() { 
  textAnimate(); 
}); 
 
function textAnimate() { 
  let processedText = ''; 
  const $textBlock = $('.text'), 
    text = $textBlock.text(), 
    textChars = text.match(/./gi), 
    textCharsLength = textChars.length, 
    animationDuration = 10; 
     
    for(let i = 0; i < textCharsLength; i++) { 
      let delay = (i / textCharsLength * animationDuration).toFixed(3); 
     
      processedText += '' + 
      '<span class="letter" style="' + 
        '-webkit-transition-delay: ' + delay + 's;' + 
        '-o-transition-delay: ' + delay + 's;' + 
        'transition-delay: ' + delay + 's;"' + 
      '>' + textChars[i] + '</span>' 
    }   
     
    $textBlock.html(processedText); 
     
    setTimeout(function() { $textBlock.addClass('show'); }, 1); 
}
.letter { 
  opacity: 0; 
  -webkit-transition: opacity .1s; 
       -o-transition: opacity .1s; 
          transition: opacity .1s; 
} 
 
.text.show .letter { 
  opacity: 1; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<p class="text"> 
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 
</p>

READ ALSO
Слияние двух объектов

Слияние двух объектов

Возникла необходимость объединения 2-х объектов в один, с соблюдением некоторых правил:

282
Динамическая таблица на Javascript

Динамическая таблица на Javascript

Прошу помощи добавить кнопку редактирования / сохранения в ячейке, рядом с другими кнопками добавления и удаления строкКнопка должна дублироваться...

517
Разница в поведении между let и var в цикле for

Разница в поведении между let и var в цикле for

Разница в объявлении счетчика цикла через let и var в том что через var переменная-счетчик видна за пределами цикла в функции, через let - только...

327
Иконка аватара без потери качества

Иконка аватара без потери качества

Добрый День! Столкнулся с проблемойСуществуют ли способы сохранения качества аватара без потери качества изображения? Проблема заключается...

315