Задать вопрос
Mr_Sergo
@Mr_Sergo

Скрипт работает неправильно после присвоении значения переменной, поможете?

Здравствуйте уважаемые форумчане!
По ссылке: https://jsfiddle.net/xrqrbcd8/4/ находится таймер обратного отсчета (для наглядности)
Выкладываю код здесь:
Разметка

<div class="timer">
    <div class="time">
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
        <div class="spaceCurPreT"></div>
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
        <div class="del">:</div>
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
        <div class="spaceCurPreT"></div>
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
        <div class="del">:</div>
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
        <div class="spaceCurPreT"></div>
        <div class="CurPre">
            <div class="pre"></div>
            <div class="cur"></div>
        </div>
    </div>
</div>


Обработчик

var interv;
interv = setInterval(timeZ,1000); var intervTimeZ=true;
 
var YourDate = 'feb 10,2033 00:00:00';
 
var alignT=false;
var spAnim = 450;
var top = 5;
var han = Number($('.cur').height() + top);
 
var can = 1; var count; var anim = []; var y = 0;
 
function timeZ(){
    commonTime = Date.parse(YourDate)/1000;
    time = commonTime - Math.floor(new Date().getTime()/1000);
    year = String(Math.floor(time / 31536000));                             rest = time - (31536000 * year);
    month = String(Math.floor(rest / 2678400));                             rest = rest - (2678400 * month);
    day = String(Math.floor(rest / 86400));                                 rest = rest - (86400 * day);
 
    hour = String(Math.floor(rest / 3600));         rest = rest - (3600 * hour);
    min = String(Math.floor(rest / 60));
    sec = String(rest - (60 * min));
    if(hour<=9){hour='0'+hour;} if(min<=9){min='0'+min;} if(sec<=9){sec='0'+sec;}
    hour = hour.split(""),      min = min.split(""),        sec = sec.split("");
    
    $('.time > .CurPre > .cur').each(function (i,el) {
        if(i==0){ $(this).html(hour[0]); }      if(i==1){ $(this).html(hour[1]); }
        if(i==2){ $(this).html(min[0]); }       if(i==3){ $(this).html(min[1]); }
        if(i==4){ $(this).html(sec[0]); }
    });
 
    if(!alignT){
        $('.time > .CurPre > .cur').each(function (i,el) {
            if(i==5){ $(this).html(sec[1]); }
            alignT=true;
        });
    }
 
    if(sec[1]==9){
        can++;
    }
 
    count = ($('.cur').length-1)-can;
    anim = [hour[0],hour[1],min[0],min[1],sec[0],sec[1]];
 
    whichAnim();
}
 
function whichAnim(){
    y++;
    if(y==1){ animTimer1(); }
    if(y==2){ animTimer2(); y=0;}
}
function animTimer1(){
    $('.cur').each(function (i,el){
        if(i > count){
            $('.pre:eq('+i+')').text(anim[i]);
            $('.pre:eq('+i+')').animate({ marginTop : top+'px' }, spAnim, function() {
                $('.cur:eq('+i+')').animate({ marginTop : (-han*2)-top+'px' }, 0);
            });
            if(can>1){can=1;}
        }
    });
}
 
function animTimer2(){
    $('.cur').each(function (i,el){
        if(i > count){
            $('.cur:eq('+i+')').text(anim[i]);
            $('.pre:eq('+i+')').animate({ marginTop : han+(top*2)+'px' }, spAnim, function() {
                $('.pre:eq('+i+')').animate({ marginTop : -han+'px' }, 0);
                $('.cur:eq('+i+')').animate({ marginTop : top+'px' }, 0);
            });
            if(can>1){can=1;}
        }
    });
}


Стили

html, body{margin: 0px;background-color: #20262e;}
 
.timer{
    width: 210px;
    margin: 10px auto 0px auto;
    font-family: Comic Sans MS;
    font-size: 20px;
    color:  #fff;
    cursor:  default;
    text-align:  center;
    line-height: 40px;
    border-radius: 10px;
    cursor:  default;
}
 
.time{
    width: 174px;
    height: 50px;
    margin: 0px auto 0px auto;
    color: #ffffff;
    padding: 10px 0px 10px 0px;
}
 
.CurPre{
    width: 25px;
    height: 50px;
    float:  left;
    overflow:  hidden;
    margin: 0px 0px 0px 0px;
}
 
.pre,.cur{
    width: 92%;
    height: 40px;
    float: left;
    background-color: #3F51B5;
    border-radius: 3px;
    box-shadow: inset 1px 1px 3px 0px rgba(255, 255, 255, 0.5);
}
 
.pre{
    margin: -45px 0px 5px 0px;
}
.cur{
    margin: 5px 0px 0px 0px;
}
 
.del{
    width: 9px;
    float:  left;
    line-height: 47px;
    margin-left: 0px;
    text-indent: 0px;
}
 
.spaceCurPreT{
    width: 2px;
    height: 5px;
    float: left;
}



Смысл в том что когда на последней плашке 0 нужно анимировать еще и предыдущую плашку, предварительно сгенерировав для нее соответствующую цифру. В приведенном коде за это отвечает переменная "can": если вторая секундная цифра является "0" то добавить can единицу, далее через цикл анимируется соответствующее количество (can) плашек сгенерировав для них соответствующую цифру, далее "can" сбрасывается на единицу что бы снова анимировалась только одна секундная плашка. В анимации или в цикле, или еще почему, я что-то делаю не так, никак не могу понять что именно.
Если после анимации двух плашек не приводить can к единице то анимация работает правильно, но если же я пишу что надо переменную can привести к единице, после того как анимировалось две плашки, то появляется глюк при анимировании соседней плашки, а именно: анимация происходит в два, а то и три раза быстрее, цифра которая генерируется для плашки- вообще генирируется не по сценарию (не тогда когда нужно).
Если обновить один или несколько раз страницу с таймером то при достижении нуля соседняя плашка вообще может не анимироваться- почему??- ведь есть сценарий по которому она просто обязана анимироваться, но нет она бывает может анимироваться а может и не анимироваться- вот этого я вообще никак не пойму. Ведь при перезагрузке страницы js-сценарий не меняется. При чем происходит это не сразу а, во-первых: при одном или нескольких обновлений страницы с таймером, во-вторых: первый раз, по достижении нуля, соседняя плашка может анимироваться по сценарию и если подождать еще 10-20 сек. то она не анимируется вообще по достижении нуля, как?? ведь страница не перезагружена, условие же "if" не может взять и пропасть.
Помогите, пожалуйста, кто-нибудь понять в чем я ошибаюсь и что нужно сделать в данной ситуации?
P.S: Если анимации второй плашки не происходит то обновите страницу с таймером.
  • Вопрос задан
  • 127 просмотров
Подписаться 1 Средний 4 комментария
Решения вопроса 2
@ksnk
Там ошибок более чем дофига. Некоторые объясняются тем, что анимация накладывается друг на друга. предыдущая анимация должна быть прекращена с помощью оператора stop перед применением.
Мрачное вычисление строкового значения времени в функции timeZ можно сократить до 2-3 строк, если вспомнить про функцию toTimeString
Ответ написан
Stalker_RED
@Stalker_RED
Для начала, разобраться зачем там столько глобальных переменных. Они там вообще не нужны, ни одна из них не должна быть глобальной.
Зачем-то каждую секунду вычисляются неиспользуемые данные, типа day, year, и какой-то rest (это что вообще?)
Зачем-то каждую секунду заново ищутся dom-элементы таймера.
can, han, spAnim, alignT - как это расшифровать? Может комментарии есть? А нет, показалось.

А как бы вы написали такой скрипт, в общих чертах?

Для начала таймер попроще
function countdown(dateStr, display) {
  let targetDate = new Date(dateStr).getTime()
  let timer = setInterval(function() {
    let now = new Date().getTime(),
        diff = targetDate - now;

    let hours = Math.floor((diff % 86400000) / 3600000),
        minutes = Math.floor((diff % 3600000) / 60000),
        seconds = Math.floor((diff % 60000) / 1000);

    document.body.innerHTML = `${hours}:${minutes}:${seconds}`
  })
}


countdown('2033-02-10 00:00:00')
https://jsfiddle.net/7uhexr41/
Затем отформатировать для вывода посимвольно
var symbols = [...document.querySelectorAll('.symbol .cur')]
function show(h, m, s) {
  var timeString =
      h.toString().padStart(2, '0')	+
      m.toString().padStart(2, '0') +
      s.toString().padStart(2, '0');

  symbols.forEach((symbol, i) => symbol.textContent = timeString[i])
}
https://jsfiddle.net/4hnxrrrt/
Меняем значение на дисплее и запускаем css анимацию
function animate(curSymbol, newValue) {
  let currentValue = curSymbol.textContent
  if (currentValue !== newValue) { // animated change
		let parent = curSymbol.parentNode
    parent.classList.remove('anim')
    curSymbol.textContent = newValue
  	curSymbol.nextElementSibling.textContent = currentValue
    var foo = parent.offsetWidth; // reflow hack
    parent.classList.add('anim')
  }
}

Осталось собрать все вместе, добавить остановку при достижении нуля и коллбек по завершению
https://jsfiddle.net/Stalk/5u6dmpqs/
и немножко переписал форматирование
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Mr_Sergo
@Mr_Sergo Автор вопроса
ksnk, Сегодня заметил что таймер по ссылке: https://jsfiddle.net/xrqrbcd8/42/ которую вы скинули, как я думаю, ошибочно выводит +3 часа, можете сами проверить, если в YourDate загнать сегодняшнюю дату (что бы проще было в уме самому посчитать) то таймер показывает на 3 часа больше чем должен, я думаю что это как-то связано с GMT, разницу в датах пробовал перевести в UTC но ничего хорошего это не дало, я его немного переписал добавив к новой дате (var date) 3 часа: https://jsfiddle.net/zlojnaxa/xrqrbcd8/56/ правильно я все сделал, я имею ввиду потом никаких глюков не должно вылезти, ну кроме как по окончании времени?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы