Come posso creare un'animazione "Please Please, Loading ..." usando jQuery?


585

Vorrei inserire sul mio sito un'animazione della filatura del cerchio "attendere, caricamento in corso". Come devo fare questo usando jQuery?

Risposte:


1211

Potresti farlo in vari modi. Potrebbe essere sottile come un piccolo stato sulla pagina che dice "Caricamento in corso ..." o forte come un intero elemento che grigie la pagina mentre i nuovi dati vengono caricati. L'approccio che sto seguendo di seguito ti mostrerà come realizzare entrambi i metodi.

Il set up

Cominciamo procurandoci una bella animazione di "caricamento" da http://ajaxload.info che useròinserisci qui la descrizione dell'immagine

Creiamo un elemento che possiamo mostrare / nascondere ogni volta che facciamo una richiesta Ajax:

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

Il CSS

Ora diamo un po 'di talento:

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

E infine, il jQuery

Va bene, su jQuery. La prossima parte è in realtà molto semplice:

$body = $("body");

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

Questo è tutto! Alleghiamo alcuni eventi all'elemento body ogni volta che vengono attivati ​​gli eventi ajaxStarto ajaxStop. Quando inizia un evento ajax, aggiungiamo la classe "caricamento" al corpo. e quando gli eventi sono terminati, rimuoviamo la classe "caricamento" dal corpo.

Guardalo in azione: http://jsfiddle.net/VpDUG/4952/


8
Questa è la soluzione più approfondita, anche se ti consiglio di utilizzare un plug-in di centraggio che centra il preloader attorno a un elemento di pagina ( ovvero body, #element o .element )
Corey Ballou,

2
Sarebbe una bella aggiunta, cballou. Stavo semplicemente cercando di ridurre al minimo le informazioni, ma come fai notare, sicuramente possono essere migliorate.
Sampson,

9
Ho dovuto usare .bind () invece di .on () dato che stiamo usando jQuery 1.5.1!
rinnegatoMind

38
Consiglio di utilizzare il plug-in che plug-in per i plug-in per assicurarsi che siano tutti collegati.
contactmatt

15
Nota: a partire da jQuery 1.8, il metodo .ajaxStop()e .ajaxStart()deve essere allegato solo al documento. docs
balexandre,

215

Per quanto riguarda l'immagine di caricamento effettiva, controlla questo sito per una serie di opzioni.

Per quanto riguarda la visualizzazione di un DIV con questa immagine quando inizia una richiesta, hai alcune scelte:

A) Mostra e nascondi manualmente l'immagine:

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

B) Usa ajaxStart e ajax Completa :

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

Usando questo l'elemento mostrerà / nasconderà per qualsiasi richiesta. Potrebbe essere buono o cattivo, a seconda delle necessità.

C) Utilizzare i singoli callback per una particolare richiesta:

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

4
Qualcosa da notare: se non puoi modificare l'HTML per aggiungere l'elemento img di caricamento, puoi farlo come immagine di sfondo sul pulsante usando CSS, ad esempio input.loading-gif {background: url ('images / loading.gif') ;} e quindi applica la classe con jQuery, ad esempio $ ('# mybutton'). addClass ('loading-gif'); L'unico problema è che questo richiederà la gif solo quando si fa clic sul pulsante di invio, che è normalmente troppo tardi, quindi è necessario pre-memorizzarlo nella cache, il che è facile con jQuery ad es. (New Image ()). Src = "images /loading.gif ";
Jackocnr,

4
Questo sito ha una selezione più ampia e, a mio avviso, più bella di caricatori con più opzioni di personalizzazione preloaders.net
rorypicko


Bella soluzione, ma quando chiamo show () dopo hide () non funziona . Ho trovato una soluzione che è switch show () e hide () per attivare (). Spero che possa aiutare qualcuno ad avere lo stesso problema del mio. Inoltre, ho provato la soluzione C) e ho fondato prima di non funzionare in modalità asincrona. Quindi, ho suggerito di chiamare show () sopra $ .ajax per funzionare correttamente.
劉鎮 瑲

Grazie mille @Paolo. Personalmente, mi è piaciuta la tua risposta rispetto a quella accettata dalla maggior parte degli utenti. Quindi, +1 a te dalla mia parte.
Ashok kumar il

113

Insieme a ciò che Jonathan e Samir hanno suggerito (entrambe eccellenti risposte tra l'altro!), JQuery ha alcuni eventi integrati che ti attiveranno quando effettui una richiesta Ajax.

C'è l' ajaxStartevento

Mostra un messaggio di caricamento ogni volta che inizia una richiesta AJAX (e nessuno è già attivo).

... ed è il fratello, l' ajaxStopevento

Allega una funzione da eseguire ogni volta che tutte le richieste AJAX sono terminate. Questo è un evento Ajax.

Insieme, rappresentano un ottimo modo per mostrare un messaggio sullo stato di avanzamento quando si verificano attività ajax in qualsiasi punto della pagina.

HTML:

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

script:

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

Questo non è aggiornato, a partire dalla 1.8.0, .ajaxStartpuò essere allegato solo al documento, ad es. $(document).ajaxStart(function(){}).
Jonno_FTW,

2
@Jonno_FTW riparato. Ta. Vecchia domanda e risposta sostituita dalle modifiche di Jonathan Sampson alla sua domanda, ma buona per tenerlo aggiornato comunque
Dan F

3
La risposta di Jonathan fu molto approfondita, ma questa per me era la migliore per la sua semplicità.
Ojonugwa Jude Ochalifu,

19

Puoi prendere una GIF animata di un cerchio che gira da Ajaxload : incollala da qualche parte nella gerarchia dei file del tuo sito web. Quindi devi solo aggiungere un elemento HTML con il codice corretto e rimuoverlo quando hai finito. Questo è abbastanza semplice:

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

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

Devi solo usare questi metodi nella tua chiamata 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();

Questo ha alcuni avvertimenti: prima di tutto, se hai due o più posti in cui è possibile mostrare l'immagine di caricamento, dovrai tenere traccia di quante chiamate vengono eseguite contemporaneamente in qualche modo e nasconderti solo quando sono tutto fatto. Questo può essere fatto usando un semplice contatore, che dovrebbe funzionare per quasi tutti i casi.

In secondo luogo, ciò nasconderà l'immagine di caricamento solo su una chiamata AJAX riuscita. Per gestire gli stati di errore, è necessario esaminare $.ajax, che è più complesso di quello $.load, $.gete simili, ma molto più flessibile troppo.


2
Grazie per la risposta. Ma dimmi, perché devo usare AJAX? Non posso semplicemente rintracciare tutto nella pagina stessa?
giovedì

Cosa vuoi esattamente rintracciare? A meno che tu non stia richiedendo informazioni dopo che la pagina è stata caricata (e AJAX è praticamente l'unico modo per farlo senza usare un plug-in), perché avresti bisogno di un'immagine di "caricamento"?
Samir Talwar,

Samir Talwar: un'applicazione JavaScript pesante in realtà. Grazie, ho avuto l'idea.
thedp

Comprensibile. In tal caso, basta chiamare showLoadingImageprima di iniziare e hideLoadingImagedopo aver finito. Dovrebbe essere abbastanza semplice. Potrebbe essere necessario inserire una sorta di setTimeoutchiamata per assicurarti che il browser esegua effettivamente il rendering del nuovo <img>tag: ho visto un paio di casi in cui non dà fastidio fino a quando JavaScript non ha terminato l'esecuzione.
Samir Talwar,

16

L'eccellente soluzione di Jonathon si interrompe in IE8 (l'animazione non mostra affatto). Per risolvere questo problema, modifica il CSS in:

.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
Modificato perché le righe multiple "background-" non funzionavano, ma la singola istruzione background funziona correttamente.
Maurice Flanagan,

7

jQuery fornisce hook di eventi per quando le richieste AJAX iniziano e finiscono. Puoi agganciarli per mostrare il tuo caricatore.

Ad esempio, creare il seguente div:

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

Impostalo su display: nonenei tuoi fogli di stile. Puoi modellarlo come preferisci. Puoi generare una bella immagine di caricamento su Ajaxload.info , se lo desideri.

Quindi, puoi utilizzare qualcosa di simile al seguente per far sì che venga mostrato automaticamente quando invii richieste Ajax:

$(document).ready(function () {

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

});

Basta aggiungere questo blocco Javascript alla fine della pagina prima chiudere il tag body o dove preferisci.

Ora, ogni volta che invii richieste Ajax, #spinnerverrà mostrato il div. Una volta completata, la richiesta verrà nuovamente nascosta.


Qualcuno può spiegare cosa c'entra AJAX con questo? Non posso semplicemente gestire tutto questo all'interno della pagina senza accedere al server con AJAX ... O mi sto perdendo qualcosa? Grazie.
thedp

4
Ah - come ho capito, volevi che un'immagine di caricamento fosse mostrata ogni volta che facevi richieste AJAX. Se vuoi semplicemente visualizzare un'animazione "Attendi, caricamento in corso ..." fino a quando la pagina non è stata caricata completamente, potresti avere un div di caricamento nella pagina e nasconderlo nel tuo blocco $ (documento).
Veeti,

7

Se stai usando Turbolink With Rails questa è la mia soluzione:

Questo è il CoffeeScript

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

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

Questo è il CSS SASS basato sulla prima eccellente risposta di Jonathan Sampson

# 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

Come Mark H ha detto, il bloccoUI è il modo.

Ex.:

<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 .: Ho preso ajax-loader.gif su http://www.ajaxload.info/



6

Con tutto il rispetto per gli altri post, hai qui una soluzione molto semplice, usando CSS3 e jQuery, senza usare ulteriori risorse o file esterni.

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

Ciò farebbe scomparire i pulsanti, quindi al loro posto apparirebbe un'animazione di "caricamento" e alla fine visualizzerebbe solo un messaggio di successo.

$(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

La maggior parte delle soluzioni che ho visto si aspetta che progettiamo un overlay di caricamento, lo mantenga nascosto e poi lo sveli quando richiesto, oppure mostri una gif o un'immagine ecc.

Volevo sviluppare un plug-in robusto, in cui con una semplice chiamata jQuery posso visualizzare la schermata di caricamento e demolirla quando l'attività è completata.

Di seguito è riportato il codice. Dipende da Font awesome e 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)); 

Basta inserire quanto sopra in un file js e includerlo in tutto il progetto.

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

Invocazione:

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

4

Si noti che quando si utilizza ASP.Net MVC, con using (Ajax.BeginForm(..., l'impostazione di ajaxStartnon funzionerà.

Utilizzare il AjaxOptionsper superare questo problema:

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


2

Per https://www.w3schools.com/howto/howto_css_loader.asp , questo è un processo in 2 passaggi senza JS:

1. Aggiungi questo HTML dove desideri lo spinner: <div class="loader"></div>

2. Aggiungi questo CSS per creare il vero spinner:

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

Poiché l'OP utilizza jQuery, è possibile chiamare $("#loader").toggle();prima di effettuare la richiesta di esecuzione prolungata per avviare l'animazione ed effettuare un'altra chiamata nella funzione di richiamata della richiesta per nasconderla.
Dmitri Chubarov,

2

Uso CSS3 per l'animazione

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.