Làm cách nào tôi có thể tạo một trò chơi Vui lòng đợi, Đang tải hình ảnh Quảng cáo sử dụng jQuery?


585

Tôi muốn đặt hoạt hình "vui lòng đợi, tải" trên trang web của mình. Làm thế nào tôi nên thực hiện điều này bằng cách sử dụng jQuery?

Câu trả lời:


1211

Bạn có thể làm điều này nhiều cách khác nhau. Nó có thể là một trạng thái tinh tế như một trạng thái nhỏ trên trang có nội dung "Đang tải ..." hoặc lớn như toàn bộ phần tử làm xám trang trong khi dữ liệu mới đang tải. Cách tiếp cận tôi đang thực hiện dưới đây sẽ chỉ cho bạn cách thực hiện cả hai phương pháp.

Cài đặt

Hãy bắt đầu bằng cách cho chúng tôi một hình ảnh động "tải" đẹp từ http://ajaxload.info Tôi sẽ sử dụngnhập mô tả hình ảnh ở đây

Hãy tạo một yếu tố mà chúng tôi có thể hiển thị / ẩn bất cứ khi nào chúng tôi thực hiện yêu cầu ajax:

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

CSS

Tiếp theo hãy cho nó một chút tinh tế:

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

Và cuối cùng, jQuery

Được rồi, vào jQuery. Phần tiếp theo này thực sự rất đơn giản:

$body = $("body");

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

Đó là nó! Chúng tôi đang gắn một số sự kiện vào yếu tố cơ thể bất cứ khi nào ajaxStarthoặc ajaxStopsự kiện được kích hoạt. Khi một sự kiện ajax bắt đầu, chúng ta thêm lớp "nạp" vào phần thân. và khi các sự kiện được thực hiện, chúng ta loại bỏ lớp "nạp" khỏi phần thân.

Xem nó trong hành động: http://jsfiddle.net/VpDUG/4952/


8
Đây là giải pháp chuyên sâu nhất mặc dù tôi khuyên bạn nên sử dụng một plugin định tâm tập trung vào trình tải trước xung quanh một thành phần trang ( ví dụ: body, #element hoặc .element )
Corey Ballou

2
Đó sẽ là một bổ sung tốt đẹp, cballou. Tôi chỉ cố gắng để giữ cho thông tin được giảm thiểu - nhưng như bạn chỉ ra, nó chắc chắn có thể được cải thiện.
Sampson

9
Tôi đã phải sử dụng .bind () thay vì .on () vì chúng tôi đang sử dụng jQuery 1.5.1!
bội ước

38
Tôi khuyên bạn nên sử dụng plugin bổ trợ cho plugin để đảm bảo tất cả chúng đều được cắm.
contactmatt

15
Lưu ý: Kể từ jQuery 1.8, phương thức .ajaxStop().ajaxStart()chỉ nên được đính kèm vào tài liệu. tài liệu
balexandre

215

Theo như hình ảnh tải thực tế, hãy xem trang web này để biết một loạt các tùy chọn.

Theo như hiển thị DIV với hình ảnh này khi yêu cầu bắt đầu, bạn có một vài lựa chọn:

A) Hiển thị thủ công và ẩn hình ảnh:

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

B) Sử dụng ajaxStartajaxComplete :

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

Sử dụng phần tử này sẽ hiển thị / ẩn cho bất kỳ yêu cầu. Có thể là tốt hay xấu, tùy thuộc vào nhu cầu.

C) Sử dụng các cuộc gọi lại riêng lẻ cho một yêu cầu cụ thể:

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

4
Một vài điều cần lưu ý: nếu bạn không thể sửa đổi HTML để thêm phần tử tải img, bạn có thể thực hiện nó dưới dạng hình nền trên nút bằng CSS, ví dụ: input.loading-gif {background: url ('hình ảnh / load.gif') ;} và sau đó áp dụng lớp với jQuery, ví dụ $ ('# mybutton'). addClass ('load-gif'); Gotcha duy nhất là điều này sẽ chỉ yêu cầu gif khi nhấp vào nút gửi, thường là quá muộn, vì vậy bạn cần phải lưu trước bộ đệm, điều này rất dễ với jQuery, ví dụ (hình ảnh mới ()). Src = " /loading.gif ";
jackocnr

4
Trang web này có một lựa chọn lớn hơn và theo ý kiến ​​của tôi là các trình tải đẹp hơn với nhiều tùy chọn tùy chỉnh hơn preloaders.net
rorypicko 22/12/13

FYI: được hợp nhất từ stackoverflow.com/questions/750353/ trên
Shog9

Giải pháp tuyệt vời, nhưng khi tôi gọi show () sau khi ẩn () thì nó không hoạt động . Tôi tìm thấy một giải pháp đó là switch show () và hide () để chuyển đổi (). Hy vọng nó có thể giúp ai đó có vấn đề tương tự như của tôi. Ngoài ra, tôi đã thử giải pháp C) và thành lập trước khi Gửi không hoạt động trong async. Vì vậy, tôi đề nghị gọi show () trên $ .ajax để hoạt động chính xác.
劉鎮

Cảm ơn bạn rất nhiều @Paolo. Cá nhân, tôi thích câu trả lời của bạn hơn câu trả lời được hầu hết người dùng chấp nhận. Do đó, +1 cho bạn từ phía tôi.
Ashok kumar

113

Cùng với những gì Jonathan và Samir đề xuất (cả hai câu trả lời xuất sắc btw!), JQuery có một số sự kiện được xây dựng mà nó sẽ kích hoạt cho bạn khi đưa ra yêu cầu ajax.

ajaxStartsự kiện

Hiển thị thông báo tải bất cứ khi nào yêu cầu AJAX bắt đầu (và không có yêu cầu nào đang hoạt động).

... và đó là anh trai, ajaxStopsự kiện

Đính kèm một chức năng để được thực thi bất cứ khi nào tất cả các yêu cầu AJAX kết thúc. Đây là một sự kiện Ajax.

Cùng nhau, họ thực hiện một cách tốt để hiển thị thông báo tiến trình khi bất kỳ hoạt động ajax nào đang diễn ra ở bất cứ đâu trên trang.

HTML:

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

Kịch bản:

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

Điều này đã lỗi thời, kể từ 1.8.0, .ajaxStartchỉ có thể được đính kèm vào tài liệu, tức là. $(document).ajaxStart(function(){}).
Jonno_FTW

2
@Jonno_FTW đã sửa. Ta. Câu hỏi và câu trả lời cũ đã được áp dụng bởi các chỉnh sửa của Jonathan Sampson cho câu hỏi của anh ấy, nhưng thật tốt để luôn cập nhật nó
Dan F

3
Câu trả lời của Jonathan rất khó hiểu, nhưng điều này đối với tôi là tốt nhất vì sự đơn giản của nó.
Ojonugwa Jude Ochalifu

19

Bạn có thể lấy một GIF hoạt hình của một vòng tròn quay từ Ajaxload - dán ở đâu đó trong chế độ gia truyền tệp trang web của bạn. Sau đó, bạn chỉ cần thêm một phần tử HTML với mã chính xác và xóa phần tử đó khi bạn hoàn tất. Điều này khá đơn giản:

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

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

Sau đó, bạn chỉ cần sử dụng các phương thức này trong cuộc gọi AJAX của mình:

$.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();

Điều này có một vài lưu ý: trước hết, nếu bạn có hai hoặc nhiều địa điểm tải hình ảnh có thể được hiển thị, bạn sẽ cần phải theo dõi xem có bao nhiêu cuộc gọi đang chạy cùng một lúc và chỉ ẩn khi chúng tất cả đã được làm xong. Điều này có thể được thực hiện bằng cách sử dụng một bộ đếm đơn giản, sẽ hoạt động cho hầu hết các trường hợp.

Thứ hai, điều này sẽ chỉ ẩn hình ảnh tải trên một cuộc gọi AJAX thành công. Để xử lý các trạng thái lỗi, bạn sẽ cần phải nhìn vào $.ajax, đó là phức tạp hơn $.load, $.getvà như thế, nhưng rất nhiều linh hoạt hơn nữa.


2
Cảm ơn vi đa trả lơi. Nhưng hãy nói cho tôi, tại sao tôi cần sử dụng AJAX? Tôi có thể đơn giản theo dõi tất cả trong trang không?
thedp

Chính xác những gì bạn muốn theo dõi? Trừ khi bạn yêu cầu thông tin sau khi trang được tải (và AJAX gần như là cách duy nhất để làm điều đó mà không cần sử dụng plugin), tại sao bạn lại cần một hình ảnh "đang tải"?
Samir Talwar

Samir Talwar: Một ứng dụng JavaScript nặng thực sự. Cảm ơn, tôi có được ý tưởng.
thedp

Có thể hiểu được. Trong trường hợp đó, chỉ cần gọi showLoadingImagetrước khi bạn bắt đầu và hideLoadingImagesau khi bạn kết thúc. Nên khá đơn giản. Bạn có thể cần phải thực hiện một số loại setTimeoutcuộc gọi để đảm bảo trình duyệt thực sự hiển thị <img>thẻ mới - tôi đã thấy một vài trường hợp không thực hiện được cho đến khi JavaScript thực thi xong.
Samir Talwar

16

Giải pháp tuyệt vời của Jonathon phá vỡ trong IE8 (hoạt hình hoàn toàn không hiển thị). Để khắc phục điều này, hãy thay đổi CSS thành:

.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
Đã chỉnh sửa vì nhiều dòng 'nền-' không hoạt động, nhưng câu lệnh nền đơn hoạt động chính xác.
Maurice Flanagan

7

jQuery cung cấp các hook sự kiện khi các yêu cầu AJAX bắt đầu và kết thúc. Bạn có thể móc vào những cái này để hiển thị trình tải của bạn.

Ví dụ: tạo div sau:

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

Đặt nó vào display: nonetrong bảng định kiểu của bạn. Bạn có thể tạo kiểu theo bất cứ cách nào bạn muốn. Bạn có thể tạo một hình ảnh tải đẹp tại Ajaxload.info , nếu bạn muốn.

Sau đó, bạn có thể sử dụng một cái gì đó như sau để làm cho nó được hiển thị tự động khi gửi các yêu cầu Ajax:

$(document).ready(function () {

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

});

Chỉ cần thêm khối Javascript này vào cuối trang của bạn trước đóng thẻ cơ thể hoặc bất cứ nơi nào bạn thấy phù hợp.

Bây giờ, bất cứ khi nào bạn gửi yêu cầu Ajax, #spinnerdiv sẽ được hiển thị. Khi yêu cầu hoàn thành, nó sẽ được ẩn lại.


Ai đó có thể vui lòng giải thích AJAX phải làm gì với điều này không? Tôi không thể đơn giản quản lý tất cả những thứ này trong trang mà không truy cập máy chủ bằng AJAX ... Hay tôi bị thiếu ở đây? Cảm ơn.
thedp

4
À - như tôi đã hiểu, bạn muốn một hình ảnh tải được hiển thị bất cứ khi nào bạn thực hiện các yêu cầu AJAX. Nếu bạn chỉ đơn giản muốn một hình ảnh động "vui lòng đợi, tải ..." sẽ được hiển thị cho đến khi trang được tải đầy đủ, bạn có thể có một div tải trong trang và sau đó ẩn nó trong khối $ (tài liệu).
Veeti

7

Nếu bạn đang sử dụng Turbolinks With Rails thì đây là giải pháp của tôi:

Đây là CoffeeScript

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

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

Đây là CSS SASS dựa trên câu trả lời xuất sắc đầu tiên từ 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

Giống như Mark H đã nói blockUI là cách.

Ví dụ.:

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

Quan sát: Tôi đã nhận được ajax-loader.gif trên http://www.ajaxload.info/


FYI: được hợp nhất từ stackoverflow.com/questions/750353/ trên
Shog9

6

Với tất cả sự tôn trọng đối với các bài đăng khác, bạn có ở đây một giải pháp rất đơn giản, sử dụng CSS3 và jQuery, mà không cần sử dụng bất kỳ tài nguyên bên ngoài cũng như các tệp nào.

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

Điều này sẽ làm cho các nút biến mất, sau đó một hình ảnh động "tải" sẽ xuất hiện ở vị trí của chúng và cuối cùng chỉ hiển thị một thông báo thành công.

$(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>');
                    });
                }
        );
    });
});

FYI: được hợp nhất từ stackoverflow.com/questions/750353/ trên
Shog9

5

Hầu hết các giải pháp tôi đã thấy đều mong muốn chúng tôi thiết kế lớp phủ tải, giữ ẩn và sau đó bỏ ẩn khi cần, hoặc hiển thị ảnh gif hoặc hình ảnh, v.v.

Tôi muốn phát triển một plugin mạnh mẽ, trong đó với một lệnh gọi jQuery đơn giản, tôi có thể hiển thị màn hình tải và xé nó khi nhiệm vụ hoàn thành.

Dưới đây là mã. Nó phụ thuộc vào Font awesome và 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)); 

Chỉ cần đặt ở trên trong một tập tin js và bao gồm nó trong suốt dự án.

Bổ sung 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;
}

Cầu nguyện:

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

4

Lưu ý rằng khi sử dụng ASP.Net MVC, với using (Ajax.BeginForm(..., hãy đặtajaxStart sẽ không hoạt động.

Sử dụng AjaxOptionsđể khắc phục vấn đề này:

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

FYI: được hợp nhất từ stackoverflow.com/questions/750353/ trên
Shog9

2

Mỗi https://www.w3schools.com/howto/howto_css_loader.asp , đây là quy trình gồm 2 bước không có JS:

1.Thêm HTML này vào nơi bạn muốn spinner: <div class="loader"></div>

2.Thêm CSS này để tạo spinner thực tế:

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

Vì OP đang sử dụng jQuery, họ có thể gọi $("#loader").toggle();trước khi thực hiện yêu cầu chạy dài để bắt đầu hoạt hình và thực hiện một cuộc gọi khác trong chức năng gọi lại của yêu cầu để ẩn nó đi.
Dmitri Chubarov

2

Tôi sử dụng CSS3 cho hoạt hình

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.