Как создать анимацию «Пожалуйста, подождите, идет загрузка…» с помощью jQuery?

585

Я хотел бы разместить анимацию вращающегося круга "Пожалуйста, подождите, загружается" на моем сайте. Как мне сделать это с помощью jQuery?

thedp
источник

Ответы:

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"); }    
});

Это оно! Мы присоединяем некоторые события к элементу body каждый раз, когда запускаются события ajaxStartили ajaxStop. Когда начинается событие ajax, мы добавляем класс «loading» в тело. и когда события завершаются, мы удаляем класс «загрузки» из тела.

Смотрите это в действии: http://jsfiddle.net/VpDUG/4952/

Сэмпсон
источник
8
Это наиболее глубокое решение, хотя я бы порекомендовал вам использовать плагин для центрирования, который центрирует предварительный загрузчик вокруг элемента страницы ( т.е. body, #element или .element )
Corey Ballou
2
Это было бы хорошим дополнением, cballou. Я просто пытался свести информацию к минимуму, но, как вы указываете, ее можно улучшить.
Сэмпсон
9
Мне пришлось использовать .bind () вместо .on (), так как мы используем jQuery 1.5.1!
renegadeMind
39
Я бы рекомендовал использовать плагин, который подключается к плагинам, чтобы убедиться, что они все подключены.
contactmatt
15
Примечание: По состоянию на JQuery 1.8, то .ajaxStop()и .ajaxStart()метод должен быть прикреплен только к документу. документы
balexandre
215

Что касается фактической загрузки изображения, проверьте этот сайт для нескольких вариантов.

Что касается отображения DIV с этим изображением в начале запроса, у вас есть несколько вариантов:

А) Вручную показать и скрыть изображение:

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

Б) Используйте 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'); Единственный недостаток в том, что это будет запрашивать GIF только при нажатии кнопки отправки, что обычно слишком поздно, поэтому вам нужно предварительно кэшировать его, что легко с jQuery, например (new Image ()). Src = "images /loading.gif ";
Jackocnr
4
Этот сайт имеет большие и по - моему выбору приятнее погрузчиков с большим количеством опций настройки preloaders.net
rorypicko
К вашему сведению: объединено со stackoverflow.com/questions/750358/…
Shog9
Хорошее решение, но когда я вызываю show () после hide (), это не работает . Я нашел решение, которое переключается show () и скрыть () toggle (). Надеясь, это может помочь кому-то иметь ту же проблему, что и моя. Кроме того, я попробовал решение C) и основал перед отправкой не работает в асинхронном режиме. Поэтому я предложил вызвать show () выше $ .ajax для правильной работы.
劉鎮瑲
Большое спасибо @Paolo. Лично мне понравился твой ответ, чем тот, который принят большинством пользователей. Следовательно, +1 тебе с моей стороны.
Ашок Кумар
113

Наряду с тем, что предложили Джонатан и Самир (между прочим, оба отличных ответа!), В jQuery есть несколько встроенных событий, которые будут срабатывать для вас при выполнении запроса ajax.

Там ajaxStartсобытие

Показывать сообщение о загрузке всякий раз, когда запускается запрос AJAX (и ни один из них уже не активен).

... и это брат, ajaxStopсобытие

Присоедините функцию, которая будет выполняться всякий раз, когда все запросы AJAX закончились. Это Ajax Event.

Вместе они создают прекрасный способ показать сообщение о прогрессе, когда где-либо на странице происходит какое-либо действие 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 исправлено. Ta. Старый вопрос и ответ, которые были заменены правками Джонатана Сэмпсона на его вопрос, но в любом случае хорошо, чтобы они были в курсе
Дэн Ф.
3
Ответ Джонатана был очень глубоким, но для меня он был лучшим из-за его простоты.
Оджонугва Джуд Очалифу
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 в конец вашей страницы, прежде чем закрывать тег body или где угодно.

Теперь, когда вы отправляете Ajax-запросы, #spinnerdiv будет отображаться. Когда запрос будет выполнен, он снова будет скрыт.

Veeti
источник
Может кто-нибудь объяснить, что AJAX имеет к этому отношение? Разве я не могу просто управлять всем этим на странице без доступа к серверу с помощью AJAX ... Или я что-то здесь упускаю? Спасибо.
thedp
4
Ах, как я понял, вы хотели, чтобы изображение загрузки отображалось при каждом выполнении запросов AJAX. Если вы просто хотите, чтобы анимация «Пожалуйста, подождите, загружается ...» отображалась до тех пор, пока страница не загрузится полностью, вы можете создать загрузочный div на странице, а затем скрыть ее в своем блоке $ (document) .ready.
Veeti
7

Если вы используете Turbolinks с 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>

Obs .: Я получил ajax-loader.gif на http://www.ajaxload.info/

bpedroso
источник
К вашему сведению: объединено со stackoverflow.com/questions/750358/…
Shog9
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>');
                    });
                }
        );
    });
});
Tsundoku
источник
К вашему сведению: объединено со stackoverflow.com/questions/750358/…
Shog9
5

Большинство решений, которые я видел, ожидают, что мы создадим оверлей загрузки, оставим его скрытым, а затем при необходимости отобразим его, или покажем изображение или изображение и т. Д.

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

Ниже приведен код. Это зависит от Font awesome и 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" }))
Рами Вайс
источник
К вашему сведению: объединено со stackoverflow.com/questions/750358/…
Shog9
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); }
}
hamx0r
источник
Поскольку OP использует 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>

Камиль
источник