Jak mogę utworzyć animację „Proszę czekać, ładowanie…” za pomocą jQuery?

585

Chciałbym umieścić na mojej stronie animację „proszę czekać, ładuję się” kołowrotek. Jak mam to zrobić za pomocą jQuery?

thedp
źródło

Odpowiedzi:

1211

Możesz to zrobić na różne sposoby. Może to być subtelny, jak mały status na stronie z napisem „Ładowanie ...”, lub tak głośny, jak cały element wyszarzający stronę podczas ładowania nowych danych. Podejście, które przyjmuję poniżej, pokaże ci, jak osiągnąć obie metody.

Ustawić

Zacznijmy od uzyskania ładnej animacji „ładowania” ze strony http://ajaxload.info, której będę używaćwprowadź opis zdjęcia tutaj

Stwórzmy element, który możemy pokazać / ukryć za każdym razem, gdy wysyłamy żądanie ajax:

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

CSS

Następnie nadajmy mu nieco stylu:

/* 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;
}

I wreszcie jQuery

W porządku, przejdź do jQuery. Ta kolejna część jest naprawdę bardzo prosta:

$body = $("body");

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

Otóż ​​to! Dołączamy niektóre zdarzenia do elementu ciała za każdym razem, gdy uruchamiane są zdarzenia ajaxStartlub ajaxStopzdarzenia. Kiedy rozpoczyna się zdarzenie ajax, dodajemy do treści klasę „loading”. a po zakończeniu zdarzeń usuwamy z treści klasę „ładującą”.

Zobacz to w akcji: http://jsfiddle.net/VpDUG/4952/

Sampson
źródło
8
Jest to najbardziej dogłębne rozwiązanie, chociaż zalecam użycie wtyczki centrującej, która centruje moduł ładowania wstępnego wokół elementu strony ( tj. Body, #element lub .element )
Corey Ballou
2
To byłby miły dodatek, cballou. Starałem się jedynie zminimalizować informacje - ale jak zauważyłeś, z pewnością można je ulepszyć.
Sampson,
9
Musiałem użyć .bind () zamiast .on (), ponieważ używamy jQuery 1.5.1!
renegadeMind
37
Polecam użycie wtyczki, która wtyczki wtyczek do wtyczek, aby upewnić się, że wszystkie są podłączone.
contactmatt
15
Uwaga: Począwszy od jQuery 1.8, metoda .ajaxStop()i .ajaxStart()powinna być dołączana tylko do dokumentu. docs
balexandre
215

Jeśli chodzi o rzeczywisty ładowany obraz, sprawdź tę stronę, aby znaleźć wiele opcji.

Jeśli chodzi o wyświetlanie DIV z tym obrazem, gdy rozpoczyna się żądanie, masz kilka możliwości:

A) Ręcznie pokaż i ukryj obraz:

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

B) Użyj ajaxStart i ajaxComplete :

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

Za pomocą tego elementu element pokaże / ukryje się dla każdego żądania. Może być dobry lub zły, w zależności od potrzeby.

C) Użyj poszczególnych oddzwonień dla konkretnego żądania:

$('#form').submit(function() {
    $.ajax({
        url: '/whatever.php',
        beforeSend: function() { $('#wait').show(); },
        complete: function() { $('#wait').hide(); }
    });
    return false;
});
Paolo Bergantino
źródło
4
Uwaga: jeśli nie możesz zmodyfikować kodu HTML, aby dodać ładujący element img, możesz to zrobić jako obraz tła na przycisku za pomocą CSS, np. Input.loading-gif {background: url ('images / loading.gif') ;}, a następnie zastosuj klasę za pomocą jQuery np. $ ('# mybutton'). addClass ('loading-gif'); Jedynym problemem jest to, że poprosi o gif tylko po kliknięciu przycisku przesyłania, co zwykle jest za późno, więc musisz go wstępnie buforować, co jest łatwe dzięki jQuery np. (New Image ()). Src = "images /loading.gif ";
jackocnr
4
Ta strona ma większy i moim zdaniem ładniejszy wybór ładowarek z większą liczbą opcji dostosowywania preloaders.net
rorypicko
Ładne rozwiązanie, ale kiedy wywołuję show () po hide (), to nie działa . Znalazłem rozwiązanie, którym jest switch show () i hide () toggle (). Mam nadzieję, że może pomóc komuś mieć taki sam problem jak mój. Wypróbowałem również rozwiązanie C) i założyłem wcześniej. Nie działaj w asynchronizacji. Zasugerowałem więc, aby wywołać show () powyżej $ .ajax, aby działać poprawnie.
瑲 瑲
Dziękuję bardzo @Paolo. Osobiście podobała mi się twoja odpowiedź niż ta zaakceptowana przez większość użytkowników. Stąd +1 do ciebie z mojej strony.
Ashok kumar
113

Oprócz tego, co zasugerowali Jonathan i Samir (obie doskonałe odpowiedzi btw!), JQuery ma wbudowane zdarzenia, które będą uruchamiane dla ciebie podczas tworzenia żądania ajax.

Jest ajaxStartwydarzenie

Pokaż komunikat ładowania przy każdym uruchomieniu żądania AJAX (i żadne nie jest już aktywne).

... i to jest brat, ajaxStopwydarzenie

Dołącz funkcję do wykonania po zakończeniu wszystkich żądań AJAX. To jest wydarzenie Ajax.

Razem stanowią świetny sposób na wyświetlenie komunikatu o postępie, gdy dowolna aktywność ajax ma miejsce w dowolnym miejscu na stronie.

HTML:

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

Scenariusz:

$(document).ajaxStart(function(){
    $('#loading').show();
 }).ajaxStop(function(){
    $('#loading').hide();
 });
Dan F.
źródło
Jest to nieaktualne, począwszy od 1.8.0, .ajaxStartmoże być dołączone tylko do dokumentu, tj. $(document).ajaxStart(function(){}).
Jonno_FTW
2
@Jonno_FTW naprawione. Ta. Stare pytanie i odpowiedź, które zostały zastąpione przez zmiany Jonathana Sampsona w jego pytaniu, ale i tak warto je aktualizować
Dan F
3
Odpowiedź Jonathana była bardzo skrupulatna, ale dla mnie ta była najlepsza ze względu na jej prostotę.
Ojonugwa Jude Ochalifu
19

Możesz pobrać animowany plik GIF obracającego się koła z Ajaxload - trzymaj go gdzieś w swojej heirarchii plików na swojej stronie. Następnie wystarczy dodać element HTML z poprawnym kodem i usunąć go, gdy skończysz. Jest to dość proste:

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

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

Następnie wystarczy użyć tych metod w wywołaniu 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();

Ma to kilka ostrzeżeń: po pierwsze, jeśli masz dwa lub więcej miejsc, w których można wyświetlić obraz ładowania, będziesz musiał sprawdzić, ile połączeń jest uruchomionych jednocześnie, i ukryć się tylko wtedy, gdy są wszystko gotowe. Można to zrobić za pomocą prostego licznika, który powinien działać w prawie wszystkich przypadkach.

Po drugie, ukryje to tylko ładowanie obrazu podczas udanego wywołania AJAX. Aby obsłużyć stany błędów, trzeba przyjrzeć się $.ajax, co jest bardziej skomplikowane niż $.load, $.geti tym podobne, ale o wiele bardziej elastyczny zbyt.

Samir Talwar
źródło
2
Dziękuję za odpowiedź. Ale powiedz mi, dlaczego w ogóle muszę korzystać z AJAX? Czy nie mogę po prostu wyśledzić tego wszystkiego na samej stronie?
thedp
Co dokładnie chcesz śledzić? Jeśli nie prosisz o informacje po załadowaniu strony (a AJAX jest właściwie jedynym sposobem na zrobienie tego bez użycia wtyczki), dlaczego w ogóle potrzebujesz obrazu „ładującego”?
Samir Talwar
Samir Talwar: Właściwie ciężka aplikacja JavaScript. Dzięki, wpadam na pomysł.
thedp
Zrozumiale. W takim przypadku wystarczy zadzwonić showLoadingImageprzed rozpoczęciem i hideLoadingImagepo zakończeniu. Powinno być dość proste. Może być konieczne wstawienie jakiegoś setTimeoutwywołania, aby upewnić się, że przeglądarka rzeczywiście renderuje nowy <img>tag - widziałem kilka przypadków, w których nie przeszkadza to, dopóki JavaScript nie zakończy działania.
Samir Talwar
16

Doskonałe rozwiązanie Jonathona pęka w IE8 (animacja wcale się nie wyświetla). Aby to naprawić, zmień CSS na:

.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)};
Ben Power
źródło
2
Edytowane, ponieważ wiele linii „w tle” nie działało, ale pojedyncza instrukcja w tle działa poprawnie.
Maurice Flanagan,
7

jQuery zapewnia przechwytywanie zdarzeń, gdy żądania AJAX zaczynają się i kończą. Możesz podłączyć się do nich, aby pokazać swój moduł ładujący.

Na przykład utwórz następujący div:

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

Ustaw to display: nonew swoich arkuszach stylów. Możesz go stylizować w dowolny sposób. Możesz wygenerować ładny obraz ładujący na Ajaxload.info , jeśli chcesz.

Następnie możesz użyć czegoś takiego jak poniżej, aby wyświetlać się automatycznie podczas wysyłania żądań Ajax:

$(document).ready(function () {

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

});

Po prostu dodaj ten blok Javascript na końcu strony przed zamknięciem tagu body lub w dowolnym innym miejscu.

Teraz, ilekroć wysyłasz żądania Ajax, #spinnerdiv zostanie wyświetlony. Po zakończeniu żądania zostanie ono ponownie ukryte.

Veeti
źródło
Czy ktoś może wyjaśnić, co AJAX ma z tym wspólnego? Czy nie mogę po prostu zarządzać tym wszystkim na stronie bez dostępu do serwera za pomocą AJAX ... A może coś tu brakuje? Dzięki.
thedp
4
Ach - jak rozumiem, chciałeś, aby obraz ładujący był pokazywany za każdym razem, gdy tworzysz żądania AJAX. Jeśli chcesz po prostu wyświetlać animację „proszę czekać, ładowanie ...” aż do pełnego załadowania strony, możesz mieć div ładowania na stronie, a następnie ukryć ją w bloku $ (dokument) .ready.
Veeti
7

Jeśli używasz Turbolinks z szynami, oto moje rozwiązanie:

To jest CoffeeScript

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

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

To jest SASS CSS oparty na pierwszej doskonałej odpowiedzi Jonathana Sampsona

# 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;
}
Fred
źródło
6

Tak jak Mark H powiedział, że blockUI jest drogą.

Dawny.:

<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 .: Mam plik ajax-loader.gif na http://www.ajaxload.info/

bpedroso
źródło
6

Z całym szacunkiem dla innych postów, masz tutaj bardzo proste rozwiązanie, używając CSS3 i jQuery, bez użycia jakichkolwiek dodatkowych zasobów zewnętrznych ani plików.

$('#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" />

João Pimentel Ferreira
źródło
5

Spowoduje to, że przyciski znikną, a następnie pojawi się animacja „ładowania” na ich miejscu, a na koniec wyświetli się komunikat o powodzeniu.

$(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
źródło
5

Większość rozwiązań, które widziałem, wymaga od nas zaprojektowania nakładki ładującej, ukrycia jej, a następnie odsłonięcia w razie potrzeby, lub pokazania gifa lub obrazu itp.

Chciałem opracować solidną wtyczkę, w której za pomocą zwykłego wywołania jQuery mogę wyświetlić ekran ładowania i zerwać go po zakończeniu zadania.

Poniżej znajduje się kod. To zależy od niesamowitej czcionki i 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)); 

Wystarczy umieścić powyższe w pliku js i dołączyć go do całego projektu.

Dodanie 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;
}

Wezwanie:

$.loadingSpinner();
$.removeLoadingSpinner();
Raj Pawan Gumdal
źródło
4

Zauważ, że podczas korzystania z ASP.Net MVC z using (Ajax.BeginForm(...ustawieniem ajaxStartnie będzie działać.

Użyj, AjaxOptionsaby rozwiązać ten problem:

(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))
Rami Weiss
źródło
2

Na https://www.w3schools.com/howto/howto_css_loader.asp jest to 2-etapowy proces bez JS:

1. Dodaj ten kod HTML w miejscu, w którym chcesz pokrętło: <div class="loader"></div>

2. Dodaj ten CSS, aby rzeczywista przędzarka:

.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
źródło
Ponieważ OP używa jQuery, mogą wywoływać $("#loader").toggle();przed długim żądaniem uruchomienia animacji i wykonać kolejne wywołanie w funkcji wywołania zwrotnego żądania, aby je ukryć.
Dmitrij Chubarow,
2

Używam CSS3 do animacji

/************ 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>

Camille
źródło