Шаг 200.
Библиотека jQuery. Прокрутка и перемещение. Прокрутка заголовков. Приостановка при наведении указателя мыши

    На этом шаге мы рассмотрим некоторые дополнительные улучшения прокрутки заголовков.

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

      $container.hover(function() {
        clearTimeout(pause);
      }, function() {
        pause = setTimeout(headlineRotate, 250);
      });

    Когда указатель мыши попадет в область заголовка, первый обработчик события .hover() вызовет функцию JavaScript clearTimeout(). Это остановит работу таймера и предотвратит вызов функции headlineRotate(). Когда указатель мыши покинет область заголовка, второй обработчик .hover() перезапустит таймер и тем самым обеспечит вызов функции headlineRotate() с 250-миллисекундной задержкой.

    В большинстве случаев этот программный код будет прекрасно справляться с решением проблемы. Однако, если пользователь несколько раз быстро переместит указатель мыши то в пределы элемента <div>, то из него, может возникнуть очень нежелательный эффект. Одновременно будут прокручиваться сразу несколько заголовков, накладываясь друг на друга.

    Для решения этой проблемы добавим еще одну переменную перед определением функции headlineRotate():

      var rotateInProgress = false;

    Теперь в самой первой строке функции мы можем проверить, не выполняется ли в настоящий момент цикл прокрутки, и продолжить работу, только если переменная rotateInProgress имеет значение false. Для этого мы обернем тело функции условной инструкцией if. Внутри условной инструкции мы тут же установим эту переменную в значение true, а в функции обратного вызова второго метода .animate() опять вернем ей значение false.

      var headlineRotate = function() {
        if (!rotateInProgress) {
          rotateInProgress = true;
          currentHeadline = (oldHeadline + 1)
            % headlineCount;
          $('div.headline').eq(oldHeadline).animate(
            {top: -hiddenPosition}, 'slow', function() {
              $(this).css('top', hiddenPosition);
            });
          $('div.headline').eq(currentHeadline).animate(
            {top: 0}, 'slow', function() {
              rotateInProgress = false;
              pause = setTimeout(headlineRotate, 5000);
            });
          oldHeadline = currentHeadline;
        }
      };

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

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

      var headlineRotate = function() {
        if (!rotateInProgress) {
          rotateInProgress = true;
          pause = false;
          currentHeadline = (oldHeadline + 1)
            % headlineCount;
          $('div.headline').eq(oldHeadline).animate(
            {top: -hiddenPosition}, 'slow', function() {
              $(this).css('top', hiddenPosition);
            });
          $('div.headline').eq(currentHeadline).animate(
            {top: 0}, 'slow', function() {
              rotateInProgress = false;
              if (!pause) {
                pause = setTimeout(headlineRotate, 5000);
              }
            });
          oldHeadline = currentHeadline;
        }
      };
      if (!pause) {
        pause = setTimeout(headlineRotate, 5000);
      }
      
      $container.hover(function() {
        clearTimeout(pause);
        pause = false;
      }, function() {
        if (!pause) {
          pause = setTimeout(headlineRotate, 250);
        }
      });

Рис.1. Окончательная версия

Полный текст этого примера можно взять здесь.

    На следующем шаге мы рассмотрим получение рассылки из другого домена.




Предыдущий шаг Содержание Следующий шаг