Gọi lại khi quá trình chuyển đổi CSS3 kết thúc


202

Tôi muốn làm mờ dần một phần tử (chuyển độ mờ của nó thành 0) và sau đó khi hoàn thành loại bỏ phần tử khỏi DOM.

Trong jQuery, điều này rất đơn giản vì bạn có thể chỉ định "Xóa" sẽ xảy ra sau khi hoạt ảnh hoàn thành. Nhưng nếu tôi muốn làm động bằng cách sử dụng các chuyển tiếp CSS3 thì có biết khi nào quá trình chuyển đổi / hoạt hình đã hoàn thành không?


3
nên tương tự như thế này: stackoverflow.com/questions/6186454/ Kẻ
Nicolas Modr gia

Câu trả lời:


334

Để chuyển đổi, bạn có thể sử dụng cách sau để phát hiện kết thúc chuyển đổi qua jQuery:

$("#someSelector").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

Mozilla có một tài liệu tham khảo tuyệt vời:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#Detecting_the_start_and_completion_of_a_transition

Đối với hình ảnh động, nó rất giống nhau:

$("#someSelector").bind("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

Lưu ý rằng bạn có thể chuyển đồng thời tất cả các chuỗi sự kiện có tiền tố trình duyệt vào phương thức bind () để hỗ trợ sự kiện bắn vào tất cả các trình duyệt hỗ trợ nó.

Cập nhật:

Theo nhận xét mà Duck để lại: bạn sử dụng .one()phương thức của jQuery để đảm bảo trình xử lý chỉ kích hoạt một lần. Ví dụ:

$("#someSelector").one("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

$("#someSelector").one("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

Cập nhật 2:

bind()Phương thức jQuery không được dùng nữa và on()phương thức này được ưa thích hơn jQuery 1.7.bind()

Bạn cũng có thể sử dụng off()phương thức trên chức năng gọi lại để đảm bảo nó sẽ chỉ được kích hoạt một lần. Đây là một ví dụ tương đương với việc sử dụng one()phương thức:

$("#someSelector")
.on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
 function(e){
    // do something here
    $(this).off(e);
 });

Người giới thiệu:


13
Điều đáng chú ý là cuộc gọi lại cũng sẽ bị loại bỏ đối với mọi phần tử con quá cảnh. Điều này rất quan trọng để ghi nhớ trong trường hợp bạn đang tự hỏi tại sao cuộc gọi lại của bạn bị sa thải nhiều lần hơn bạn mong đợi. Tôi không nhận thức được bất kỳ công việc xung quanh như bây giờ.
Lev

22
@Lev bạn có thể dễ dàng giảm thiểu điều này bằng cách so sánh TargetTarget của sự kiện với mục tiêu của nó. Vì vậy, một cái gì đó như: function (event) {if (event.target === event.cienTarget) {/ * Làm công cụ * /}}
Jim Jeffers

5
Vâng, tôi đã tìm ra điều đó ngay sau khi tôi viết bình luận. > _ <Cảm ơn bạn đã đăng nó mặc dù; Tôi chắc chắn rằng nó sẽ giúp người khác! :)
Lev

9
Chúng tôi sử dụng .on()thay vì .bind()cho jQuery v1.7 + api.jquery.com/bind
olo

4
Tất cả các trình duyệt hiện đại hiện hỗ trợ sự kiện chưa được chuẩn bị. caniuse.com/#feat=css-transitions Cũng lưu ý rằng nếu bạn có "chuyển đổi webkitTransitionEnd", nó sẽ được kích hoạt hai lần trong Chrome.
Michael S.

17

Một tùy chọn khác là sử dụng Khung chuyển tiếp jQuery để xử lý các chuyển tiếp CSS3 của bạn. Các hiệu ứng / hiệu ứng chuyển tiếp hoạt động tốt trên các thiết bị di động và bạn không phải thêm một dòng chuyển tiếp CSS3 lộn xộn trong tệp CSS của mình để thực hiện các hiệu ứng hoạt hình.

Dưới đây là một ví dụ sẽ chuyển độ mờ của phần tử thành 0 khi bạn nhấp vào nó và sẽ bị xóa sau khi quá trình chuyển đổi hoàn tất:

$("#element").click( function () {
    $('#element').transition({ opacity: 0 }, function () { $(this).remove(); });
});

Demo Fiddle


Cuộc gọi lại không hoạt động - có thể là do sự thay đổi trong api quá cảnh mà tôi không biết, nhưng ví dụ bí mật không hoạt động. Nó kích hoạt phương thức ẩn trước khi hoạt hình chạy (thử trong chrome)
Jonathan Liuti

@JonathanLiuti đã thử nghiệm bằng FireFox 25, IE11, Chrome 31. Hoạt động tốt.
ROFLwTIME

Yea @ROFLwTIME bạn hoàn toàn đúng - có vẻ như chrome của tôi đang phát điên. Đã kiểm tra lại câu đố hôm nay sau khi chrome khởi động lại và nó hoạt động như mong đợi. Lỗi của tôi ! Xin lỗi 'cái này.
Jonathan Liuti

14

Có một animationendsự kiện có thể được quan sát xem tài liệu ở đây , cũng cho transitionhoạt hình css bạn có thể sử dụng transitionendsự kiện

Không cần thêm thư viện, tất cả đều hoạt động với vanilla JS

document.getElementById("myDIV").addEventListener("transitionend", myEndFunction);
function myEndFunction() {
	this.innerHTML = "transition event ended";
}
#myDIV {transition: top 2s; position: relative; top: 0;}
div {background: #ede;cursor: pointer;padding: 20px;}
<div id="myDIV" onclick="this.style.top = '55px';">Click me to start animation.</div>


2
Đây là một câu trả lời chỉ liên kết đường biên giới . Bạn nên mở rộng câu trả lời của mình để bao gồm nhiều thông tin ở đây và chỉ sử dụng liên kết để tham khảo.
Tạm biệt StackExchange

4
Bỏ phiếu này vì đây là lần đầu tiên không dựa vào jQuery. Không có ý nghĩa chặt hạ toàn bộ một cây cho một nhánh.
Aaron Mason

7

Đối với bất kỳ ai mà điều này có thể hữu ích, đây là một hàm phụ thuộc jQuery mà tôi đã thành công với việc áp dụng hoạt hình CSS thông qua một lớp CSS, sau đó nhận được một cuộc gọi lại từ sau đó. Nó có thể không hoạt động hoàn hảo vì tôi đã sử dụng nó trong Ứng dụng Backbone.js, nhưng có thể hữu ích.

var cssAnimate = function(cssClass, callback) {
    var self = this;

    // Checks if correct animation has ended
    var setAnimationListener = function() {
        self.one(
            "webkitAnimationEnd oanimationend msAnimationEnd animationend",
            function(e) {
                if(
                    e.originalEvent.animationName == cssClass &&
                    e.target === e.currentTarget
                ) {
                    callback();
                } else {
                    setAnimationListener();
                }
            }
        );
    }

    self.addClass(cssClass);
    setAnimationListener();
}

Tôi đã sử dụng nó như thế này

cssAnimate.call($("#something"), "fadeIn", function() {
    console.log("Animation is complete");
    // Remove animation class name?
});

Ý tưởng ban đầu từ http://mikefowler.me/2013/11/18/page-transitions-in-backbone/

Và điều này có vẻ tiện dụng: http://api.jqueryui.com/addClass/


Cập nhật

Sau khi vật lộn với đoạn mã trên và các tùy chọn khác, tôi sẽ khuyên bạn nên thận trọng với bất kỳ kết thúc nghe hoạt hình CSS nào. Với nhiều hình ảnh động đang diễn ra, điều này có thể trở nên lộn xộn rất nhanh cho việc nghe sự kiện. Tôi thực sự muốn đề xuất một thư viện hoạt hình như GSAP cho mọi hoạt hình, ngay cả những thư viện nhỏ.


Cảm ơn đã chia sẻ nó, tôi đã sử dụng nó và chỉnh sửa thêm e.stopImmediatePropagation(); self.trigger(this.whichAnimationEvent()); //for purge existing event callback.apply(self);
BomAle

5

Câu trả lời được chấp nhận hiện kích hoạt hai lần cho hình động trong Chrome. Có lẽ điều này là do nó nhận ra webkitAnimationEndcũng như animationEnd. Sau đây chắc chắn sẽ chỉ bắn một lần:

/* From Modernizr */
function whichTransitionEvent(){

    var el = document.createElement('fakeelement');
    var transitions = {
        'animation':'animationend',
        'OAnimation':'oAnimationEnd',
        'MSAnimation':'MSAnimationEnd',
        'WebkitAnimation':'webkitAnimationEnd'
    };

    for(var t in transitions){
        if( transitions.hasOwnProperty(t) && el.style[t] !== undefined ){
            return transitions[t];
        }
    }
}

$("#elementToListenTo")
    .on(whichTransitionEvent(),
        function(e){
            console.log('Transition complete!  This is the callback!');
            $(this).off(e);
        });

3
Tôi sẽ đề nghị gọi hàm whichAnimationEvent (), vì nó liên quan đến các sự kiện hoạt hình.
Jakob Løkke Madsen
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.