Статьи

Цепочка таймера в JavaScript

Только недавно я работал над проектом, в котором мне нужно было реализовать функцию, которая обычно реализуется с помощью gif. Мне нужно было создать 4 изображения — скажем, 1, A, B, C, наложенные друг на друга для последовательного отображения. И затем, после того, как первый набор из 4 изображений был отображен, повторяется аналогичная последовательность, но с изменением только первого изображения, то есть 2, A, B, C. И затем третий набор — 3, A, B, C ,

Теперь, поскольку образец, который мне пришлось воспроизвести, был создан в формате gif, я предполагаю, что создать такое изображение с помощью программного обеспечения для редактирования изображений довольно легко. Моей задачей было воспроизвести этот эффект, используя чистый JavaScript. Более того, так как это было только на этапе разработки, мне приходилось проектировать для гибкости, поскольку требования могут меняться в любой момент времени. К счастью, для меня дизайн для гибкости — огромный поворот. Несмотря на первоначальные трудности, огромное удовлетворение, которое вы получаете от этого, когда видите изменения требований и способность сказать своим клиентам, что вы можете осуществить изменения в течение 10 секунд, полностью стоит времени и энергии, которые вы вкладываете в течение этого времени. начальные этапы развития.

Для моего эксперимента гибкость, которую я должен был включить, состояла в том, чтобы иметь возможность изменять продолжительность, в течение которой каждое из 4 изображений может отображаться, если требования изменились. Если бы это был gif-файл, это была бы простая задача, просто измените время в приложении, и тогда оно будет готово. Покажите клиенту, и если это не то, что он / она хочет, то повторите то же самое.

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

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

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

Итак, как я приступил к созданию такой системы.

Обо всем по порядку.

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

Первое, что я сделал, — создал объект, содержащий все значения, для которых я хочу, чтобы каждая из фаз выполнялась.

var settings = {
  duration1:2000, //Millisecond duration for the first timer
  duration2:300, //Millisecond duration for the second timer.
  duration3:300, //Millisecond duration for the third timer.
  duration4:300, //Millisecond duration for the fourth timer.
 };

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

var phaseTimeouts =  {
  'phase1':
   {
    duration:settings.duration1,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase2':
   {
    duration:settings.duration2,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase3':
   {
    duration:settings.duration3,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase4':
   {
    duration:settings.duration4,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
 }

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

var timeOutSetter = function(){
   
   //Call the terminating function of the previous phase
   phaseTimeouts['phase'+currentPhaseId].end(currentPhaseId);
    
   //If there is anything left in phaseTimeouts array
   //create a new timer and update the new timerId
   var nextPhaseKey = 'phase'+(currentPhaseId+1);
   if(phaseTimeouts[nextPhaseKey]){
    currentPhaseId++;
    console.log('Entering Next Phase : ' + nextPhaseKey);
    currentTimerId = setTimeout(timeOutSetter,phaseTimeouts[nextPhaseKey].duration);
   }
  };

Приведенная выше функция ничего не делает, а объединяет различные таймеры вместе, используя настройки из объекта phaseTimeouts. Переменная phaseTimeouts является неправильным, поскольку она захватывает больше, чем просто тайм-аут, и, возможно, может использоваться для привязки дополнительной функциональности.

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

Ниже приведен фрагмент кода в полном объеме

$(function(){
 
 var settings = {
  duration1:2000, //Millisecond duration for the first timer
  duration2:300, //Millisecond duration for the second timer.
  duration3:300, //Millisecond duration for the third timer.
  duration4:300, //Millisecond duration for the fourth timer.
 };
  
 var phaseTimeouts =  {
  'phase1':
   {
    duration:settings.duration1,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase2':
   {
    duration:settings.duration2,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase3':
   {
    duration:settings.duration3,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
  ,
  'phase4':
   {
    duration:settings.duration4,
    end : function(currentPhaseId){
     console.log('Ending phase : '+ currentPhaseId);
    }
   }
 }
  
 //Once all the contents of the window finishes loading, start the slideshow
 $(window).load(function(){
   
  var currentPhaseId = 1;
  var currentTimerId = 0;
   
  var timeOutSetter = function(){
   
   //Call the terminating function of the previous phase
   phaseTimeouts['phase'+currentPhaseId].end(currentPhaseId);
    
   //If there is anything left in phaseTimeouts array
   //create a new timer and update the new timerId
   var nextPhaseKey = 'phase'+(currentPhaseId+1);
   if(phaseTimeouts[nextPhaseKey]){
    currentPhaseId++;
    console.log('Entering Next Phase : ' + nextPhaseKey);
    currentTimerId = setTimeout(timeOutSetter,phaseTimeouts[nextPhaseKey].duration);
   }
  };
   
  var currentTimerId = setTimeout(timeOutSetter,phaseTimeouts['phase1'].duration);
   
 });
  
});

  Раздвоенный дизайн может быть настолько захватывающим, не так ли?