Як я можу створити анімацію «Будь ласка, зачекайте, завантажуючи…» за допомогою jQuery?


585

Я хотів би розмістити на своєму сайті анімацію спінінг-кола "будь ласка, зачекай, завантажуй". Як мені це зробити за допомогою jQuery?

Відповіді:


1211

Ви могли це зробити різними способами. Це може бути тонким, як невеликий статус на сторінці з написом "Завантаження ...", або ж голосний, як цілий елемент, що переносить сторінку, коли нові дані завантажуються. Підхід, який я застосовую нижче, покаже вам, як досягти обох методів.

Налаштування

Почнемо з того, щоб отримати нам приємну "завантажувальну" анімацію з http://ajaxload.info, яку я буду використовувативведіть тут опис зображення

Давайте створимо елемент, який ми можемо показати / приховати будь-коли, коли ми робимо запит на ajax:

<div class="modal"><!-- Place at bottom of page --></div>

CSS

Далі давайте трохи почуття:

/* Start by setting display:none to make this hidden.
   Then we position it in relation to the viewport window
   with position:fixed. Width, height, top and left speak
   for themselves. Background we set to 80% white with
   our animation centered, and no-repeating */
.modal {
    display:    none;
    position:   fixed;
    z-index:    1000;
    top:        0;
    left:       0;
    height:     100%;
    width:      100%;
    background: rgba( 255, 255, 255, .8 ) 
                url('http://i.stack.imgur.com/FhHRx.gif') 
                50% 50% 
                no-repeat;
}

/* When the body has the loading class, we turn
   the scrollbar off with overflow:hidden */
body.loading .modal {
    overflow: hidden;   
}

/* Anytime the body has the loading class, our
   modal element will be visible */
body.loading .modal {
    display: block;
}

І нарешті, jQuery

Гаразд, на jQuery. Наступна частина насправді дуже проста:

$body = $("body");

$(document).on({
    ajaxStart: function() { $body.addClass("loading");    },
     ajaxStop: function() { $body.removeClass("loading"); }    
});

Це воно! Ми приєднуємо деякі події до елемента тіла в будь-який час, ajaxStartабо ajaxStopподії запускаються. Коли починається подія "Аякс", ми додаємо до тіла клас "завантаження". і коли події виконані, ми видаляємо клас "завантаження" з тіла.

Дивіться це в дії: http://jsfiddle.net/VpDUG/4952/


8
Це найбільш глибоке рішення, хоча я б рекомендував вам використовувати плагін для центрування, який центрирує попереднє завантаження навколо елемента сторінки ( тобто body, #element, або .element )
Corey Ballou

2
Це було б приємне доповнення, cballou. Я просто намагався мінімізувати інформацію - але, як ви зазначаєте, це, безумовно, можна покращити.
Сампсон

9
Мені довелося використовувати .bind () замість .on (), оскільки ми використовуємо jQuery 1.5.1!
renegadeMind

37
Я рекомендую використовувати плагін, який додає до плагінів, щоб переконатися, що вони всі підключені.
contactmatt

15
Примітка: Станом на jQuery 1.8, .ajaxStop()і .ajaxStart()метод слід додавати лише до документа. docs
balexandre

215

Що стосується фактичного завантаження зображення, перегляньте на цьому сайті купу варіантів.

Що стосується відображення DIV з цим зображенням, коли починається запит, у вас є кілька варіантів:

A) Показати та приховати зображення вручну:

$('#form').submit(function() {
    $('#wait').show();
    $.post('/whatever.php', function() {
        $('#wait').hide();
    });
    return false;
});

B) Використовуйте ajaxStart і ajaxComplete :

$('#wait').ajaxStart(function() {
    $(this).show();
}).ajaxComplete(function() {
    $(this).hide();
});

Використовуючи це, елемент відображатиме / приховує будь-який запит. Може бути добрим чи поганим, залежно від потреби.

C) Використовуйте індивідуальні зворотні дзвінки для конкретного запиту:

$('#form').submit(function() {
    $.ajax({
        url: '/whatever.php',
        beforeSend: function() { $('#wait').show(); },
        complete: function() { $('#wait').hide(); }
    });
    return false;
});

4
Щось зауважимо: якщо ви не можете змінити HTML, щоб додати елемент img для завантаження, ви можете зробити це як фонове зображення на кнопці за допомогою CSS, наприклад, input.loading-gif {background: url ('images / loading.gif') ;}, а потім застосуйте клас за допомогою jQuery, наприклад $ ('# mybutton'). addClass ('loading-gif'); Єдине, що це вимагає, щоб графік запитував лише при натисканні кнопки подання, що зазвичай занадто пізно, тому вам потрібно попередньо кешувати його, що легко за допомогою jQuery, наприклад (new Image ()). Src = "images /loading.gif ";
jackocnr

4
На цьому сайті є більший і, на мій погляд, приємніший вибір навантажувачів з більшою кількістю параметрів налаштування preloaders.net
rorypicko


Приємне рішення, але коли я дзвоню show () після сховання (), він не працює . Я знайшов рішення, яке полягає у переключенні show () та hid (() для переключення (). Сподіваючись, що це може допомогти комусь із таких же проблем, як і моя. Також я спробував рішення C) і заснував ранішеSend, що не працює в системі async. Отже, я запропонував зателефонувати show () вище $ .ajax, щоб правильно працювати.
劉鎮 瑲

Дуже дякую @Paolo. Особисто мені сподобалась ваша відповідь, ніж відповідь, яку прийняла більшість користувачів. Отже, +1 від вас з мого боку.
Ашок кумар

113

Поряд із тим, що запропонували Джонатан та Самір (обидва відмінні відповіді btw!), JQuery має деякі вбудовані події, які він запустить для вас під час запиту на ajax.

Там ajaxStartподія

Показуйте повідомлення про завантаження кожного разу, коли починається запит AJAX (і жодне вже не активне).

... і це брат, ajaxStopподія

Приєднайте функцію, яка виконується щоразу, коли всі запити AJAX закінчуються. Це подія Ajax.

Разом вони створюють чудовий спосіб відобразити повідомлення про хід роботи, коли будь-яка діяльність у програмі Ajax відбувається де-небудь на сторінці.

HTML:

<div id="loading">
  <p><img src="loading.gif" /> Please Wait</p>
</div>

Сценарій:

$(document).ajaxStart(function(){
    $('#loading').show();
 }).ajaxStop(function(){
    $('#loading').hide();
 });

Це застаріло, станом на 1.8.0, .ajaxStartможе бути додане лише до документа, тобто. $(document).ajaxStart(function(){}).
Jonno_FTW

2
@Jonno_FTW виправлено. Та. Старе запитання та відповіді, що витіснили редакції Джонатана Сампсона на його запитання, але добре, щоб все одно було оновлено
Dan F

3
Відповідь Джонатана була дуже чіткою, але це для мене було найкращим за її простоту.
Ojonugwa Jude Ochalifu

19

Ви можете захопити анімований GIF від спінального кола з Ajaxload - дотримуйтесь його десь у вашому веб-сайті. Тоді вам просто потрібно додати HTML-елемент із правильним кодом та видалити його, коли закінчите. Це досить просто:

function showLoadingImage() {
    $('#yourParentElement').append('<div id="loading-image"><img src="path/to/loading.gif" alt="Loading..." /></div>');
}

function hideLoadingImage() {
    $('#loading-image').remove();
}

Тоді вам просто потрібно використовувати ці методи у своєму дзвінку AJAX:

$.load(
     'http://example.com/myurl',
     { 'random': 'data': 1: 2, 'dwarfs': 7},
     function (responseText, textStatus, XMLHttpRequest) {
         hideLoadingImage();
     }
);

// this will be run immediately after the AJAX call has been made,
// not when it completes.
showLoadingImage();

У цьому є декілька застережень: насамперед, якщо у вас є два або більше місць, де може бути показано завантажувальне зображення, вам потрібно буде відстежувати кількість викликів, які виконуються одразу, і ховати лише тоді, коли вони все зроблено. Це можна зробити за допомогою простого лічильника, який повинен працювати майже у всіх випадках.

По-друге, це приховає лише завантажувальне зображення під час успішного дзвінка AJAX. Для обробки стану помилки, ви повинні дивитися на $.ajax, який є більш складним , ніж $.load, $.getтощо, але набагато більш гнучким теж.


2
Дякую за відповідь. Але скажіть, для чого мені взагалі потрібно використовувати AJAX? Не можу я просто відстежити все це на самій сторінці?
thedp

Що саме ви хочете відстежувати? Якщо ви не вимагаєте інформації після завантаження сторінки (а AJAX - це майже єдиний спосіб зробити це без використання плагіна), навіщо вам взагалі потрібне "завантаження" зображення?
Самір Тальвар

Самір Тальвар: Насправді важка програма JavaScript. Дякую, я розумію.
thedp

Зрозуміло. У такому випадку просто зателефонуйте showLoadingImageперед тим, як почати і hideLoadingImageпісля того, як закінчите. Повинен бути досить простим. Можливо, вам доведеться ввести якийсь setTimeoutвиклик, щоб переконатися, що браузер фактично видає новий <img>тег - я бачив кілька випадків, коли він не турбує, поки JavaScript не закінчить виконання.
Самір Тальвар

16

Чудове рішення Джонатана перерва в IE8 (анімація взагалі не показується). Щоб виправити це, змініть CSS на:

.modal {
display:    none;
position:   fixed;
z-index:    1000;
top:        0;
left:       0;
height:     100%;
width:      100%;
background: rgba( 255, 255, 255, .8 ) 
            url('http://i.stack.imgur.com/FhHRx.gif') 
            50% 50% 
            no-repeat;
opacity: 0.80;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
filter: alpha(opacity = 80)};

2
Відредаговано тому, що декілька рядків 'background-' не працювали, але один оператор background працює правильно.
Моріс Фланаган

7

jQuery забезпечує гачки подій, коли запити AJAX починаються та закінчуються. Ви можете підключити їх, щоб показати свій навантажувач.

Наприклад, створіть такий div:

<div id="spinner">
  <img src="images/spinner.gif" alt="Loading" />
</div>

Встановіть це display: noneу своїх таблицях стилів. Ви можете стилізувати його будь-яким способом. Ви можете створити приємне завантажувальне зображення на Ajaxload.info , якщо хочете.

Потім ви можете скористатися чимось таким, щоб автоматично відображатися при надсиланні запитів на Ajax:

$(document).ready(function () {

    $('#spinner').bind("ajaxSend", function() {
        $(this).show();
    }).bind("ajaxComplete", function() {
        $(this).hide();
    });

});

Просто додайте цей блок Javascript до кінця вашої сторінки раніше закривати тег тіла або куди не вважаєте за потрібне.

Тепер, коли ви надсилаєте запити на Ajax, #spinnerбуде показано div. Коли запит буде завершено, він буде знову прихований.


Може хтось, будь ласка, пояснить, що AJAX стосується цього? Не можу я просто керувати цим все на сторінці, не звертаючись до сервера за допомогою AJAX ... Або я щось тут пропускаю? Дякую.
thedp

4
Ах - як я зрозумів, ви хотіли, щоб завантажувальне зображення відображалось кожного разу, коли ви робили запити AJAX. Якщо ви просто хочете, щоб анімація "будь ласка, зачекайте, завантажується ..." буде показана, поки сторінка не завантажиться повністю, ви можете мати файл завантаження на сторінці, а потім приховати його у вашому блоці $ (document) .ready.
Veeti

7

Якщо ви використовуєте Turbolinks With Rails, це моє рішення:

Це CoffeeScript

$(window).on 'page:fetch', ->
  $('body').append("<div class='modal'></div>")
  $('body').addClass("loading")

$(window).on 'page:change', ->
  $('body').removeClass("loading")

Це SASS CSS на основі першої чудової відповіді Джонатана Сампсона

# loader.css.scss

.modal {
    display:    none;
    position:   fixed;
    z-index:    1000;
    top:        0;
    left:       0;
    height:     100%;
    width:      100%;
    background: rgba( 255, 255, 255, 0.4)
            asset-url('ajax-loader.gif', image)
            50% 50% 
            no-repeat;
}
body.loading {
    overflow: hidden;   
}

body.loading .modal {
    display: block;
}

6

Як Марк Н сказав, що блокUI - це шлях.

Наприклад:

<script type="text/javascript" src="javascript/jquery/jquery.blockUI.js"></script>
<script>
// unblock when ajax activity stops
$(document).ajaxStop($.unblockUI); 

$("#downloadButton").click(function() {

    $("#dialog").dialog({
        width:"390px",
        modal:true,
        buttons: {
            "OK, AGUARDO O E-MAIL!":  function() {
                $.blockUI({ message: '<img src="img/ajax-loader.gif" />' });
                send();
            }
        }
    });
});

function send() {
    $.ajax({
        url: "download-enviar.do",          
        type: "POST",
        blablabla
    });
}
</script>

Порада .: Я отримав ajax-loader.gif на http://www.ajaxload.info/



6

При всій повазі до інших публікацій, у вас тут дуже просте рішення, використовуючи CSS3 та jQuery, не використовуючи жодних додаткових зовнішніх ресурсів та файлів.

$('#submit').click(function(){
  $(this).addClass('button_loader').attr("value","");
  window.setTimeout(function(){
    $('#submit').removeClass('button_loader').attr("value","\u2713");
    $('#submit').prop('disabled', true);
  }, 3000);
});
#submit:focus{
  outline:none;
  outline-offset: none;
}

.button {
    display: inline-block;
    padding: 6px 12px;
    margin: 20px 8px;
    font-size: 14px;
    font-weight: 400;
    line-height: 1.42857143;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    -ms-touch-action: manipulation;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    background-image: none;
    border: 2px solid transparent;
    border-radius: 5px;
    color: #000;
    background-color: #b2b2b2;
    border-color: #969696;
}

.button_loader {
  background-color: transparent;
  border: 4px solid #f3f3f3;
  border-radius: 50%;
  border-top: 4px solid #969696;
  border-bottom: 4px solid #969696;
  width: 35px;
  height: 35px;
  -webkit-animation: spin 0.8s linear infinite;
  animation: spin 0.8s linear infinite;
}

@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  99% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  99% { transform: rotate(360deg); }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="submit" class="button" type="submit" value="Submit" />


5

Це призвело б до зникнення кнопок, тоді на їх місці з’явиться анімація «завантаження» і нарешті просто відобразиться повідомлення про успіх.

$(function(){
    $('#submit').click(function(){
        $('#submit').hide();
        $("#form .buttons").append('<img src="assets/img/loading.gif" alt="Loading..." id="loading" />');
        $.post("sendmail.php",
                {emailFrom: nameVal, subject: subjectVal, message: messageVal},
                function(data){
                    jQuery("#form").slideUp("normal", function() {                 
                        $("#form").before('<h1>Success</h1><p>Your email was sent.</p>');
                    });
                }
        );
    });
});


5

Більшість рішень, які я бачив, або очікує, що ми створимо накладку для завантаження, збережемо її прихованою, а потім приховаємо, коли потрібно, або покажемо gif або зображення тощо.

Я хотів розробити надійний плагін, де за допомогою просто дзвінка jQuery я можу відобразити екран завантаження і зруйнувати його, коли завдання буде виконано.

Нижче - код. Це залежить від дивовижного шрифту та jQuery:

/**
 * Raj: Used basic sources from here: http://jsfiddle.net/eys3d/741/
 **/


(function($){
    // Retain count concept: http://stackoverflow.com/a/2420247/260665
    // Callers should make sure that for every invocation of loadingSpinner method there has to be an equivalent invocation of removeLoadingSpinner
    var retainCount = 0;

    // http://stackoverflow.com/a/13992290/260665 difference between $.fn.extend and $.extend
    $.extend({
        loadingSpinner: function() {
            // add the overlay with loading image to the page
            var over = '<div id="custom-loading-overlay">' +
                '<i id="custom-loading" class="fa fa-spinner fa-spin fa-3x fa-fw" style="font-size:48px; color: #470A68;"></i>'+
                '</div>';
            if (0===retainCount) {
                $(over).appendTo('body');
            }
            retainCount++;
        },
        removeLoadingSpinner: function() {
            retainCount--;
            if (retainCount<=0) {
                $('#custom-loading-overlay').remove();
                retainCount = 0;
            }
        }
    });
}(jQuery)); 

Просто покладіть вище у js-файл і включіть його в проект.

Додавання CSS:

#custom-loading-overlay {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    background: #000;
    opacity: 0.8;
    filter: alpha(opacity=80);
}
#custom-loading {
    width: 50px;
    height: 57px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -28px 0 0 -25px;
}

Виклик:

$.loadingSpinner();
$.removeLoadingSpinner();

4

Зауважте, що при використанні ASP.Net MVC, з using (Ajax.BeginForm(..., встановленнямajaxStart не буде працювати.

Використовуйте AjaxOptionsдля подолання цього питання:

(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))


2

На https://www.w3schools.com/howto/howto_css_loader.asp , це двоетапний процес без JS:

1.Додайте цей HTML, де ви хочете, щоб спінер: <div class="loader"></div>

2.Додайте цей CSS, щоб зробити фактичний спінер:

.loader {
    border: 16px solid #f3f3f3; /* Light grey */
    border-top: 16px solid #3498db; /* Blue */
    border-radius: 50%;
    width: 120px;
    height: 120px;
    animation: spin 2s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

Оскільки ОП використовує jQuery, вони можуть зателефонувати $("#loader").toggle();перед тим, як зробити тривалий запит, щоб запустити анімацію та здійснити ще один виклик у функції зворотного дзвінка запиту, щоб приховати її.
Дмитро Чубаров

2

Я використовую CSS3 для анімації

/************ CSS3 *************/
.icon-spin {
  font-size: 1.5em;
  display: inline-block;
  animation: spin1 2s infinite linear;
}

@keyframes spin1{
    0%{transform:rotate(0deg)}
    100%{transform:rotate(359deg)}
}

/************** CSS3 cross-platform ******************/

.icon-spin-cross-platform {
  font-size: 1.5em;
  display: inline-block;
  -moz-animation: spin 2s infinite linear;
  -o-animation: spin 2s infinite linear;
  -webkit-animation: spin 2s infinite linear;
  animation: spin2 2s infinite linear;
}

@keyframes spin2{
    0%{transform:rotate(0deg)}
    100%{transform:rotate(359deg)}
}
@-moz-keyframes spin2{
    0%{-moz-transform:rotate(0deg)}
    100%{-moz-transform:rotate(359deg)}
}
@-webkit-keyframes spin2{
    0%{-webkit-transform:rotate(0deg)}
    100%{-webkit-transform:rotate(359deg)}
}
@-o-keyframes spin2{
    0%{-o-transform:rotate(0deg)}
    100%{-o-transform:rotate(359deg)}
}
@-ms-keyframes spin2{
    0%{-ms-transform:rotate(0deg)}
    100%{-ms-transform:rotate(359deg)}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>


<div class="row">
  <div class="col-md-6">
    Default CSS3
    <span class="glyphicon glyphicon-repeat icon-spin"></span>
  </div>
  <div class="col-md-6">
    Cross-Platform CSS3
    <span class="glyphicon glyphicon-repeat icon-spin-cross-platform"></span>
  </div>
</div>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.