Pull to refresh

Делаем полноценный JS-прелоадер для AJAX-приложения

Reading time5 min
Views38K
Многие программисты оптимизируют JavaScript и CSS-код, чтобы страница грузилась быстрее.
Но не все они делают прелоадеры, которые дают пользователю эффект субъективно более быстрой загрузки.

Способ №1. Дешево и сердито.
Идея проста — необходимо поместить по центру картинку, которая будет показывать пользователю, что страница все еще загружается. Код довольно прост, пишем сразу после <body>:

  1. <div id="preloaderbg" class="centerbg1">
  2.   <div class="centerbg2">
  3.     <div id="preloader"></div>
  4.   </div>
  5. </div>
  6.  
  7. <script type="text/javascript">
  8. document.getElementById('preloaderbg').style.display = 'block';
  9. document.body.style.overflow = 'hidden';
  10. </script>
* This source code was highlighted with Source Code Highlighter.


CSS-код:

  1. .centerbg1 {
  2.   display: none;
  3.   width:100%;
  4.   height:100%;
  5.   position: absolute;
  6.   top: 0px;
  7.   left: 0px;
  8.   z-index: 1000;
  9.   background: url('/design/im/texture1.jpg') #3c363e;
  10. }
  11.  
  12. .centerbg2 {
  13.   position: absolute;
  14.   left: 50%;
  15.   top: 50%;
  16. }
  17.  
  18. #preloader {
  19.   top: -50%;
  20.   left: -50%;
  21.   position: relative;
  22.   width: 333px;
  23.   height: 26px;
  24.   background: url('/content/pages/articles/preloaders/bg2.gif');
  25.   border: solid #edda3d 2px;
  26. }
* This source code was highlighted with Source Code Highlighter.


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

Потом, когда все загрузилось — нужно убрать прелоадер и установить overflow в положение visible.

  1. document.getElementById('loaderbg').style.display = 'none';
  2. document.body.style.overflow = 'visible';
* This source code was highlighted with Source Code Highlighter.


Эту часть кода я поместил в файл с JS-функциями, plreloader1.js

Если делать прогрессбар из анимированного GIF-рисунка, то он может получиться слишком тяжелым, порой даже больше самой странички, где его размещают.
Поэтому лучше нарисовать полоску (например, такую), поставить ее как фон у блока с ID preloader и двигать бекграунд-позишн по таймеру.

  1. <script type="text/javascript">
  2.   document.getElementById('loaderbg').style.display = 'block';
  3.   document.body.style.overflow = 'hidden';
  4.   pbPos = 0;
  5.   pbInt = setInterval(function() {
  6.   document.getElementById('preloader').style.backgroundPosition = ++pbPos + 'px 0';
  7.   }, 25);
  8. </script>
* This source code was highlighted with Source Code Highlighter.


И после загрузки делаем вот что:
  1. clearInterval(pbPos);
  2. document.getElementById('loaderbg').style.display = 'none';
* This source code was highlighted with Source Code Highlighter.


Результат работы можно посмотреть тут.

У этого способа есть недостатки — Если ставить скрытие прелоадера на onload, т.е. когда ждать, пока загрузятся все картинки, то пользователь может подумать, что страница просто зависла — фактически кроме анимации ничего не происходит. Если же вешать на $(document).ready() из jQuery, то после исчезновения прелоадера картинки только будут подгружаться.

Поэтому предлагается использовать…

Способ №2. Истина где-то рядом, или джедаи наносят ответный удар.
Для начала нарисуем 2 полосы загрузки — активную и не очень.

Неактивная полоса
Активная полоса

Поставим неактивную как фон, а активную сделаем фоном у дива, для которого будем менять ширину в зависимости от процента загрузки.

  1. <div id="loaderbg" class="centerbg1">
  2.  <div class="centerbg2">
  3.   <div id="preloader">
  4.    <img alt="Загрузка..." src="/design/im/progbar_ph.gif" />
  5.    <div id="progbarfg"></div>
  6.   </div>
  7.  </div>
  8. </div>
* This source code was highlighted with Source Code Highlighter.


progbar_ph.gif – это картинка высотой в 1 пиксель и шириной с нашу полосу прокрутки (данный пример глючит без нее в IE, и я пока не нашел другого способа выровнять по центру див с прогрессбаром).
Стили такие же, как и в предыдущем способе, разве что
#progbarfg {width: 0px; background: url(‘/design/im/progbar_fg.png’)}


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

Возьмем средний сайт, сделанный полностью на AJAX. Загрузка примерно происходит так:
  • грузится HTML-код
  • начинают грузиться картинки
  • затем некий фреймворк
  • дополнительные JS-файлы (хотя лучше все склеить в один)
  • запускается некая функция (или несколько), которая стягивает дополнительный контент.

Всему этому (за вычетом CSS и HTML) мы назначаем вес в байтах (или условный вес), например, единицу, и по мере загрузки каждого файла (или выполнения функции) мы двигаем наш прогрессбар.

Я реализовал 2 метода — первый простой, включается так:
непосредственно перед </body> пишем:

<script type="text/javascript">
dLoader.start('progbarfg', 333, 'count');
</script>


Первым параметром идет идентификатор блока с активной полосой загрузки в качестве фона, вторым — ширина картинки, третий параметр — это метод, которым будем считать вес контента.

Скрипт сканирует все картинки на страницы и назначает им вес равный 1. Все JS-файлы прописываются в его теле, как я расскажу чуть ниже.
Однако хочется, чтобы вес у каждой единицы контента был не единицей, а реальным объемом в байтах. Да и для AJAX-приложений хотелось бы сразу подгрузить всю графику.

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

Так что дописав перед </body> следущее, мы получим прогрессбар, который будет показывать ход загрузки всего контента на странице, после чего плавно исчезнет.

  1. <script type="text/javascript">
  2.   dLoader.start('mainprogbarfg', 333, 'size', function(){ $('#preloaderbg').fadeOut(250); });
  3. </script>
* This source code was highlighted with Source Code Highlighter.


Когда загрузились все JS-файлы, запускаются функции, которые есть в массиве invoke. Если мы с помощью jQuery подгружаем контент, то функция будет выглядить так:

  1. function fn(callBack){
  2. $.get('/', params, function(data){ someHandler(data); eval(callBack); });
  3. }
* This source code was highlighted with Source Code Highlighter.


PHP-скрипт делает следующее: он заносит в массив необходимые скрипты с их размерами, а так же картинки и дополнительные функции. Код:

  1. $data['js'] = array(
  2.   array('path' => 'jquery-1.2.6.min.js', 'size' => filesize($jsRoot.'/jquery-1.2.6.min.js')),
  3.   array('path' => 'functions.js', 'size' => filesize($jsRoot.'/functions.js'))
  4. );
  5. $data['im'] = GetFiles($imgRoot, true);
  6. $data['invoke'][] = array(
  7.   'action' => 'loadTemplates',
  8.   'size' => GetDirSize(dirname(__FILE__).'/design/ajax templates/', false)
  9. );
  10. $data['jspath'] = '/design/js/';
  11. $data['impath'] = '/design/im';
* This source code was highlighted with Source Code Highlighter.


Уже после того, как загрузились все картинки и JS-файлы, вызывается событие onLoad, которое вы указали в функции dLoader.start()

Еще есть способ кастомизации процесса загрузки:

  1. dLoader.userProgress = function(bytesLoaded, totalBytes){ doSmth(); }
* This source code was highlighted with Source Code Highlighter.


Для того, чтобы использовать это, нужно отредактировать PHP-скрипт, прописав в нем свои пути и JS-библиотеки, затем запустить его, чтобы он сгенерировал скрипт загрузчика, который потом нужно прописать в <head> единственным скриптом.
Работающий пример второго варианта лежит здесь.

Архив со скриптами можно взять отсюда, ну а посмотреть, как это все работает — на моем сайте.

Работает в Internet Explorer 6/7, Firefox 3, Opera 9.5, Safari 3.2.1

Пожелания и предложения приветствуются :)

Спасибо за помощь в подготовке статьи waitekk отсыпьте ему кармы а мне еще травы
Tags:
Hubs:
Total votes 63: ↑53 and ↓10+43
Comments35

Articles