2009-08-02 20 views
31

Tôi nghĩ nó sẽ đơn giản nhưng tôi vẫn không thể làm cho nó hoạt động được. Bằng cách nhấp vào một nút, tôi muốn một số hoạt ảnh xảy ra - cái khác sau - nhưng bây giờ tất cả các hoạt ảnh đang diễn ra cùng một lúc. Dưới đây là mã của tôi - một người nào đó có thể vui lòng cho tôi biết nơi tôi sẽ sai ?:Làm thế nào tôi có thể tạo hiệu ứng động nhiều phần tử theo tuần tự bằng jQuery?

$(".button").click(function(){ 
    $("#header").animate({top: "-50"}, "slow") 
    $("#something").animate({height: "hide"}, "slow") 
    $("ul#menu").animate({top: "20", left: "0"}, "slow") 
    $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); 
}); 
+0

6.9kb được nhận xét, chưa được rút gọn và không được nén. Prob <1kb trong thực tế – redsquare

+1

Tôi đang tìm cách làm một điều rất giống với câu hỏi này, vì vậy tôi đã tạo một plugin Jquery nhỏ (https://github.com/fillswitch/Jquery-Sequential-Animations). Hy vọng nó sẽ giúp một số người khác ra! –

Trả lời

23

Bạn có thể làm một loạt các callbacks.

$(".button").click(function(){ 
    $("#header").animate({top: "-50"}, "slow", function() { 
     $("#something").animate({height: "hide"}, "slow", function() { 
      $("ul#menu").animate({top: "20", left: "0"}, "slow", function() { 
       $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");   
      }); 
     }); 
    }); 
}); 
+0

xem ở trên! . – redsquare

+0

Điều đó đã hiệu quả. Cheers jammus. – lnvrt

+4

Tôi gặp vấn đề tương tự trên trang web của mình và tôi đã từng nghĩ đến việc sử dụng các cuộc gọi lại, nhưng có vẻ như không đủ để làm như vậy. nó sẽ được tốt đẹp nếu bạn bằng cách nào đó có thể làm điều đó với chuỗi jquery. tại thời điểm tôi làm điều đó bằng cách sử dụng chức năng chậm trễ: animate điều đầu tiên. trì hoãn điều thứ hai bởi cùng một lượng thời gian tôi đang làm động thứ đầu tiên, sau đó tạo hiệu ứng động .. và cứ thế. – MrVimes

-8

Sử dụng tùy chọn queue:

$(".button").click(function(){ 
    $("#header").animate({top: "-50"}, { queue: true, duration: "slow" }) 
    $("#something").animate({height: "hide"}, { queue: true, duration: "slow" }) 
    $("ul#menu").animate({top: "20", left: "0"}, { queue: true, duration: "slow" }) 
    $(".trigger").animate({height: "show", top: "110", left: "0"}, { queue: true, duration: "slow" }); 
}); 
+0

Cảm ơn Garrett, nhưng nó không hoạt động ... – lnvrt

+0

hàng đợi là đúng theo mặc định – redsquare

+0

vậy, phải làm gì? – lnvrt

28

Queue chỉ hoạt động nếu bạn tạo hiệu ứng động cùng một nguyên tố. Chúa biết tại sao ở trên đã bình chọn lên nhưng nó sẽ không hoạt động.

Bạn sẽ cần sử dụng gọi lại hoạt ảnh. Bạn có thể truyền vào một hàm làm tham số cuối cùng cho hàm animate và nó sẽ được gọi sau khi hoạt ảnh đã hoàn thành. Tuy nhiên, nếu bạn có nhiều hoạt ảnh lồng nhau với callbacks thì tập lệnh sẽ không thể đọc được.

Tôi đề xuất plugin following viết lại hàm animate jQuery gốc và cho phép bạn chỉ định tên hàng đợi. Tất cả các hoạt ảnh mà bạn thêm cùng với tên hàng đợi sẽ được chạy tuần tự như được minh họa here.

Ví dụ kịch bản

$("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); 
    $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); 
    $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); 
+0

Vâng, gọi lại là những gì tôi sẽ đề nghị. –

+0

Cảm ơn redsquare. Nhưng vì sẽ không có rất nhiều hoạt hình diễn ra, tôi không nghĩ rằng cần một plugin (thêm 6.26kb). Tôi sẽ ghi nhớ nó trong tương lai. – lnvrt

+0

cảm ơn thông tin @redsquare. :) –

1

Bạn cũng có thể đặt hiệu ứng vào cùng một hàng đợi, tức là hàng đợi của phần tử BODY.

$('.images IMG').ready(
    function(){ 
     $('BODY').queue(
      function(){ 
       $('.images').fadeTo('normal',1,function(){$('BODY').dequeue()}); 
      } 
     ); 
    } 
); 

Đảm bảo bạn gọi dequeue() trong lần gọi lại hiệu ứng cuối cùng.

1

này đã được trả lời tốt (Tôi nghĩ rằng câu trả lời của jammus là tốt nhất) nhưng tôi nghĩ rằng tôi muốn cung cấp một lựa chọn dựa trên làm thế nào tôi làm điều này trên trang web của tôi, bằng cách sử dụng chức năng delay() ...

$(".button").click(function(){ 
    $("#header").animate({top: "-50"}, 1000) 
    $("#something").delay(1000).animate({height: "hide"}, 1000) 
    $("ul#menu").delay(2000).animate({top: "20", left: "0"}, 1000) 
    $(".trigger").delay(3000).animate({height: "show", top: "110", left: "0"}, "slow"); 
}); 

(thay thế 1000 bằng tốc độ hoạt ảnh mong muốn của bạn. Ý tưởng là độ trễ của bạn bị trì hoãn bởi số tiền đó và tích lũy độ trễ trong hoạt ảnh của mỗi phần tử. Vì vậy, nếu hoạt ảnh của bạn là 500 miliseconds, giá trị độ trễ của bạn sẽ là 500, 1000, 1500)

chỉnh sửa: Tốc độ 'chậm' của FYI jquery cũng là 600 mili giây. vì vậy nếu bạn muốn sử dụng 'chậm' trong hoạt ảnh của mình, chỉ cần sử dụng các giá trị này trong mỗi lần gọi tiếp theo đến chức năng trễ - 600, 1200, 1800

+0

Điều này dường như không phải là rất năng động phương pháp seing rằng bạn phải cập nhật thủ công các giá trị này – neufuture

+0

Đây là cách tôi đã làm ne nó trong quá khứ và lý do tôi kết thúc ở đây tức là để có được một phương pháp tốt hơn nhưng điều này không làm việc, và bạn có thể thiết lập các biến cho thời gian của các hình ảnh động và sử dụng chúng trong sự chậm trễ để bạn sẽ chỉ phải cập nhật thời gian như bình thường ... sau đó có vẻ như không có nhược điểm ?? –

+0

Một giải pháp đơn giản nhanh chóng +1 – suspectus

2

Mở rộng câu trả lời của jammus, điều này có lẽ thực tế hơn một chút chuỗi các hoạt ảnh. Gửi một danh sách, sinh động mỗi lần lượt, gọi đệ quy gọi là animate một lần nữa với một danh sách giảm. Thực hiện gọi lại khi tất cả đã hoàn tất.

Danh sách ở đây là các phần tử được chọn, nhưng có thể là danh sách các đối tượng phức tạp hơn chứa các thông số hoạt ảnh khác nhau trên mỗi hoạt ảnh.

Here is a fiddle

$(document).ready(function() { 
    animate([$('#one'), $('#two'), $('#three')], finished); 
}); 

function finished() { 
    console.log('Finished'); 
} 

function animate(list, callback) { 
    if (list.length === 0) { 
     callback(); 
     return; 
    } 
    $el = list.shift(); 
    $el.animate({left: '+=200'}, 1000, function() { 
     animate(list, callback); 
    }); 
} 
25

Tôi biết đây là một câu hỏi cũ, nhưng nó phải được cập nhật với một câu trả lời cho các phiên bản mới hơn jQuery (1.5 trở lên):

Sử dụng $.when chức năng bạn có thể viết helper này:

function queue(start) { 
    var rest = [].splice.call(arguments, 1), 
     promise = $.Deferred(); 

    if (start) { 
     $.when(start()).then(function() { 
      queue.apply(window, rest); 
     }); 
    } else { 
     promise.resolve(); 
    } 
    return promise; 
} 

Sau đó, bạn có thể gọi nó như thế này:

queue(function() { 
    return $("#header").animate({top: "-50"}, "slow"); 
}, function() { 
    return $("#something").animate({height: "hide"}, "slow"); 
}, function() { 
    return $("ul#menu").animate({top: "20", left: "0"}, "slow"); 
}, function() { 
    return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");   
}); 
+0

Cập nhật tốt đẹp! Rất gọn gàng và hoạt động như dự định. – Bora

+2

Nó là một mô hình rất đẹp. Một đề xuất nữa - IE 8 (ít nhất) đề cập đến đối tượng "đối số" khác nhau. Đầu tiên, nó cần phải được tạo thành một mảng thực, sau đó phương thức .splice cần cả hai tham số. Sử dụng \t var args = Array.prototype.slice.cuộc gọi (đối số); \t var rest = [] .splice.call (args, 1, args.length-1); – jschrab

+1

Cảm ơn, điều này đã giúp tôi rất nhiều. –

6

Một cải tiến nhẹ về câu trả lời @ schmunk là để sử dụng hàng đợi đối tượng jQuery đối tượng đơn giản để tránh xung đột với các hoạt ảnh không liên quan khác:

$({}) 
    .queue(function (next) { 
     elm1.fadeOut('fast', next); 
    }) 
    .queue(function (next) { 
     elm2.fadeIn('fast', next); 
    }) 
    // ... 

Một điều cần lưu ý là, mặc dù tôi chưa bao giờ gặp phải vấn đề khi thực hiện việc này, theo the docs sử dụng các phương thức xếp hàng trên một trình bao bọc đối tượng đơn giản không được hỗ trợ chính thức.

Làm việc với Plain Objects

Hiện nay, các hoạt động chỉ được hỗ trợ trên các đối tượng Javascript đơn giản bọc trong jQuery là: .data() ,. prop() ,. bind(), .unbind() , .trigger() và .triggerHandler().

+2

Đây là một giải pháp thanh lịch vì nó tránh được các cuộc gọi lại làm tổ sâu sắc. Tôi đã lắp ráp một chút [jsFiddle] (http://jsfiddle.net/philippm/SFLAB/) mà đặt điều này vào hành động. Về sự hỗ trợ của các đối tượng được bao bọc bằng phẳng: [hướng dẫn jQuery chính thức] (http://learn.jquery.com/effects/uses-of-queue-and-dequeue/) sử dụng cách tiếp cận tương tự. – Philipp

2

Animate Nhiều Thẻ tuần tự

Bạn có thể tận dụng jQuery tích hợp trong hoạt hình xếp hàng, nếu bạn chỉ cần chọn một thẻ như cơ thể để làm xếp hàng toàn cầu:

// Convenience object to ease global animation queueing 
$.globalQueue = { 
    queue: function(anim) { 
     $('body') 
     .queue(function(dequeue) { 
      anim() 
      .queue(function(innerDequeue) { 
       dequeue(); 
       innerDequeue(); 
      }); 
     }); 

     return this; 
    } 
}; 

// Animation that coordinates multiple tags 
$(".button").click(function() { 
    $.globalQueue 
    .queue(function() { 
     return $("#header").animate({top: "-50"}, "slow"); 
    }).queue(function() { 
     return $("#something").animate({height: "hide"}, "slow"); 
    }).queue(function() { 
     return $("ul#menu").animate({top: "20", left: "0"}, "slow"); 
    }).queue(function() { 
     return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); 
    }); 
}); 

http://jsfiddle.net/b9chris/wjpL31o0/

Vì vậy, , đây là lý do tại sao tính năng này hoạt động và hoạt động như thế nào:

  1. Cuộc gọi đến $.globalQueue.queue() chỉ đang xếp hàng một cuộc gọi đến hoạt ảnh của thẻ của bạn, nhưng nó xếp hàng đó vào thẻ body.

  2. Khi jQuery truy cập hoạt ảnh thẻ trong hàng đợi, hoạt ảnh của thẻ bắt đầu, trên hàng đợi cho thẻ của bạn - nhưng cách hoạt ảnh của khung công tác jQuery hoạt động. trường hợp này) để tạm dừng, cho đến khi hoạt ảnh tùy chỉnh gọi hàm được truyền vào trong hàm dequeue(). Vì vậy, mặc dù hàng đợi cho thẻ và nội dung hoạt ảnh của bạn là riêng biệt, hàng đợi của thẻ body hiện đang đợi cho số gọi dequeue() của nó. http://api.jquery.com/queue/#queue-queueName-callback

  3. Chúng tôi chỉ cần thực hiện mục đang đợi cuối cùng trên hàng đợi của thẻ một lời kêu gọi tiếp tục xếp hàng toàn cầu bằng cách gọi hàm dequeue() của nó - đó là những gì gắn hàng đợi nhau.

  4. Để thuận tiện, phương thức globalQueue.queue trả về tham chiếu this để dễ dàng chuỗi.

setInterval

Vì lợi ích của sự hoàn chỉnh, thật dễ dàng với đất ở đây chỉ tìm kiếm một sự thay thế cho setInterval - đó là bạn không quá nhiều tìm cách để làm cho hình ảnh động riêng biệt phối hợp, như chỉ bắn chúng trên thời gian mà không có sự gia tăng đột biến phía trước trong hoạt hình của bạn gây ra bởi cách các trình duyệt mới hơn sẽ trì hoãn hàng đợi hoạt hình và bộ hẹn giờ để tiết kiệm CPU.

Bạn có thể thay thế một cuộc gọi đến setInterval như thế này:

setInterval(doAthing, 8000); 

Với điều này:

/** 
* Alternative to window.setInterval(), that plays nicely with modern animation and CPU suspends 
*/ 
$.setInterval = function (fn, interval) { 
    var body = $('body'); 
    var queueInterval = function() { 
     body 
     .delay(interval) 
     .queue(function(dequeue) { 
      fn(); 
      queueInterval(); 
      dequeue(); // Required for the jQuery animation queue to work (tells it to continue animating) 
     }); 
    }; 
    queueInterval(); 
}; 

$.setInterval(doAthing, 8000); 

http://jsfiddle.net/b9chris/h156wgg6/

Và tránh những vụ nổ vụng về của hình ảnh động khi một tab nền có hình ảnh động của nó được kích hoạt lại bởi trình duyệt.

Các vấn đề liên quan