×

Ёлка с таймером для блога

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

Постановка задачи

Необходимо написать ёлку, которая по мере приближения нового года будет становиться зеленее. Под ёлкой должен быть таймер, который бы отсчитывал время до нового года.

Поиск решения

Я решил не оформлять это всё плагином, т.к ёлка всего лишь временный элемент оформления. Отделять логику от представления это конечно хорошо, но времени на освоение процесса написания плагинов к WordPress’у меня не было.

Самый простой вариант – вывести ёлку средствами PHP, а для анимации и таймера использовать jQuery. Это тоже не самое оптимальное решение, т.к. использовать фреймворк весом в 70 КБ ради экономии пары строчек кода – плохая практика. Зато время написания скриптика заметно сократилось.

Часть первая — Подготовка картинки

По изначальному замыслу ёлка должна была заполняться снизу вверх. Самый простой вариант – сделать две картинки и играться с их размерами.

Для ускорения процесса была найдена картинка из набора бесплатных иконок. Затем средствами графического редактора картинка была обесцвечена. В итоге получили два файла одинаковых размеров: для цветной ёлки и для чёрно-белого варианта.

Часть вторая — Логика на PHP

Ёлка должна нормально выводиться еще до того момента, когда загрузится jQuery, т.к. JS включен не у всех.

Первым делом нужно выбрать точку начального отсчета, которая будет соответствовать максимальному времени до нового года. Выбирать промежутком год глупо, т.к. в процентном соотношении год это очень много. Самое логичное выбрать периодом последний месяц года.

Сначала я думал средствами PHP менять размер ёлки раз в день, а потом уже на JS потихоньку заполнять исходя из таймера. Но потом решил что процент заполнения картинки будет считаться на основе часов, оставшихся до нового года, т.к.люди у меня всё равно записи долго не читают и не заметят анимированного изменения ёлки.

Размер моей картинки по высоте – 207 px. В верхней части у неё есть черная граница высотой 5 px, которая не изменит свой цвет. Менять будет 202px картинки. В декабре 744 часа, именно это количество мы возьмём за 100%.

if(date(n) == 12){   $imageSize = round((202/100)*(100 - (744 - date(j)*24)/(744/100)));//высчитываем размер картинки }else{   $imageSize = 207; }

В переменной imageSize мы получаем размер цветной картинки, которую будем помещать поверх церно-белой.

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

function declension($n,$string=array('день','дня','дней')){//функция для склонения подписей   $n = abs($n) % 100;   $n1 = $n % 10;   if ($n > 10 && $n < 20) return $string[2];   if ($n1 > 1 && $n1 < 5) return $string[1];   if ($n1 == 1) return $string[0];   return $string[2]; }

Ей достаточно передать число и три склонения для описания этого числа. Вот так это будет выглядеть у нас в коде.

if(date(j) != 1 and date(n) != 1){   //высчитываем числа   $dayLeft = 31 - date(j);   $hoursLeft = 23 - date(G) - 3;   $minutesLeft = 59 - date(i);   $secondsLeft = 59 - date(s);            //создаём подписи   $daySign = declension($dayLeft,$string=array('день','дня','дней'));   $hoursSign = declension($hoursLeft,$string=array('час','часа','часов'));   $minutesSign = declension($minutesLeft,$string=array('минута','минуты','минут'));   $secondsSign = declension($secondsLeft,$string=array('секунда','секунды','секунд')); }else{   $congratulation = "С новым 2011 годом!"; }

Тут есть один нюанс. Функция date() возвращает время на сервере. И если дома у меня всё было хорошо, то у хостера время не совпадает с московским. А я хочу чтобы стартовым временем было именно московское. Поэтому из переменной $hoursLeft я вычитаю разницу в три часа.

Часть третья — Выводим HTML и CSS

С HTML всё просто. Для ёлки делаем для вложенных слоя. Для таймера отдельный слой внизу.

<div id="new-year-back-box">   <div id="new-year-image-td">     <div id="new-year-image">&nbsp;     </div>   </div>   <div id="new-year-text">     <p>       <?if(!isset($congratulation)){?>         До нового года:</p>         <p>           <span id="dayLeft" class="number"><?=$dayLeft?></span> <span id="daySign"><?=$daySign?></span>           <span id="hoursLeft" class="number"><?=$hoursLeft?></span> <span id="hoursSign"><?=$hoursSign?></span>         </p>         <p>           <span id="minutesLeft" class="number"><?=$minutesLeft?></span> <span id="minutesSign"><?=$minutesSign?></span>           <span id="secondsLeft" class="number"><?=$secondsLeft?></span> <span id="secondsSign"><?=$secondsSign?></span>       <?}else{         echo $congratulation;       }?>     </p>   </div> </div>

C CSS всё также просто. Высчитанный ранее размер картинки используется в стиле для цветной каритнки #new-year-image в качестве высоты. Тут же ей задаётся отрицательный верхний отступ.

<style>   #new-year-back-box{     margin-top:10px;     width:200px;     background:url(/*путь к картинке*//chrtree-gray.png) center top no-repeat;     border:0px;     font-size:16px;   }              #new-year-image-td{     position: relative;     height:207px;     text-align:center;   }              #new-year-image{     position: absolute;     height:<?=$imageSize?>px;     width:160px;     background:url(/*путь к картинке*//chrtree-color.png) center -<?echo (207 - $imageSize)?>px no-repeat;     bottom:0px;     left:20px;   }              #new-year-text{     text-align:center;   }              .number{     font-size:20px;   } </style>

Собственно, с этого момента мы уже можем посмотреть на ёлку, вот только таймер не двигается.

Часть четвёртая — Оживляем таймер с помощью jQuery

Т.к. за день ёлка заполнится только на 7px, то нет смысла анимировать процесс заполнения картинки. Он будет незаметен для пользователя, но таймер нам нужен.

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

<script>   $(document).ready(function(){     var date = new Date();     if(date.getMonth() == 11){       setInterval(refreshTime, 1000);     }   });              var NYDate = new Date("1 Jan 2011 00:00");              function refreshTime(){     var date = new Date();     var leftTime = NYDate - date;                  var dayLeft = Math.floor(leftTime/86400000);     var hoursLeft = Math.floor(leftTime/3600000) - 24*dayLeft;     var minutesLeft = Math.floor(leftTime/60000) - 1440*dayLeft - 60*hoursLeft;     var secondsLeft = Math.floor(leftTime/1000) - 86400*dayLeft - 3600*hoursLeft - 60*minutesLeft;                  var daySign = declension(dayLeft,['день','дня','дней']);     var hoursSign = declension(hoursLeft,['час','часа','часов']);     var minutesSign = declension(minutesLeft,['минута','минуты','минут']);     var secondsSign = declension(secondsLeft,['секунда','секунды','секунд']);                  $('#dayLeft').html(dayLeft);     $('#daySign').html(daySign);     $('#hoursLeft').html(hoursLeft);     $('#hoursSign').html(hoursSign);     $('#minutesLeft').html(minutesLeft);     $('#minutesSign').html(minutesSign);     $('#secondsLeft').html(secondsLeft);     $('#secondsSign').html(secondsSign);   }              function declension(n,string){//функция для склонения подписей     var n = Math.abs(n) % 100;     var n1 = n % 10;     if (n > 10 && n < 20) return string[2];     if (n1 > 1 && n1 < 5) return string[1];     if (n1 == 1) return string[0];     return string[2];   } </script>

А т.к. JS получает дату с компьютера пользователя, то все посетители увидят правильный таймер =)

На этом всё.

logo