โทรกลับในการเปลี่ยน CSS


คำตอบ:


82

ฉันรู้ว่า Safari ใช้การเรียกกลับwebkitTransitionEndที่คุณสามารถแนบโดยตรงกับองค์ประกอบที่มีการเปลี่ยนแปลง

ตัวอย่างของพวกเขา (จัดรูปแบบใหม่เป็นหลายบรรทัด):

box.addEventListener( 
     'webkitTransitionEnd', 
     function( event ) { 
         alert( "Finished transition!" ); 
     }, false );

มีสิ่งเดียวกันสำหรับเบราว์เซอร์อื่นหรือไม่?
แม้ว

6
ใช่ 'Transitionend' สำหรับ Mozilla และ 'oTransitionEnd' ใน Opera
qqryq

2
เท็จในตอนท้ายทำอะไร?
แม้ว

@meo มันมีบางอย่างที่เกี่ยวข้องกับthisองค์ประกอบภายในการเรียกกลับ แต่เป็นพารามิเตอร์ที่จำเป็นดังนั้นในกรณีนี้จึงเป็นไปตามข้อกำหนดเท่านั้น
Doug Neiner

8
@DougNeiner เท็จในตอนท้ายสำหรับuseCaptureMode. เมื่อเกิดเหตุการณ์ขึ้นจะมีสองช่วง - ระยะแรกคือโหมดจับภาพส่วนที่สองคือโหมดฟองสบู่ ในโหมดจับภาพเหตุการณ์จะลดลงจากองค์ประกอบของร่างกายไปยังองค์ประกอบที่ระบุ จากนั้นจะเข้าสู่โหมดฟองซึ่งจะย้อนกลับ พารามิเตอร์เท็จขั้นสุดท้ายระบุว่าคุณต้องการให้ตัวฟังเหตุการณ์เกิดขึ้นในโหมดฟอง วิธีใช้อย่างหนึ่งคือการแนบตัวจัดการเหตุการณ์ก่อนที่จะต้องใช้ในโหมดฟองสบู่ =) 37signals.com/svn/posts/…
rybosome

103

ใช่หากเบราว์เซอร์รองรับสิ่งดังกล่าวเหตุการณ์จะถูกทริกเกอร์เมื่อการเปลี่ยนแปลงเสร็จสมบูรณ์ อย่างไรก็ตามเหตุการณ์จริงแตกต่างกันระหว่างเบราว์เซอร์:

  • ใช้เบราว์เซอร์ Webkit (Chrome, Safari) webkitTransitionEnd
  • Firefox ใช้ transitionend
  • IE9 + ใช้ msTransitionEnd
  • Opera ใช้ oTransitionEnd

อย่างไรก็ตามคุณควรตระหนักว่าwebkitTransitionEndอย่ายิงเสมอไป! สิ่งนี้ทำให้ฉันเห็นหลายครั้งและดูเหมือนว่าจะเกิดขึ้นหากภาพเคลื่อนไหวจะไม่มีผลต่อองค์ประกอบ ในการหลีกเลี่ยงปัญหานี้ควรใช้การหมดเวลาเพื่อเริ่มการทำงานของตัวจัดการเหตุการณ์ในกรณีที่ไม่ถูกทริกเกอร์ตามที่คาดไว้ ดูบล็อกโพสต์เกี่ยวกับปัญหานี้ได้ที่นี่: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/ <- 500 ข้อผิดพลาดภายในเซิร์ฟเวอร์

ด้วยเหตุนี้ฉันจึงมักจะใช้เหตุการณ์นี้ในส่วนของรหัสที่มีลักษณะดังนี้:

var transitionEndEventName = "XXX"; //figure out, e.g. "webkitTransitionEnd".. 
var elemToAnimate = ... //the thing you want to animate..
var done = false;
var transitionEnded = function(){
     done = true;
     //do your transition finished stuff..
     elemToAnimate.removeEventListener(transitionEndEventName,
                                        transitionEnded, false);
};
elemToAnimate.addEventListener(transitionEndEventName,
                                transitionEnded, false);

//animation triggering code here..

//ensure tidy up if event doesn't fire..
setTimeout(function(){
    if(!done){
        console.log("timeout needed to call transition ended..");
        transitionEnded();
    }
}, XXX); //note: XXX should be the time required for the
        //animation to complete plus a grace period (e.g. 10ms) 

หมายเหตุ: ในการรับชื่อสิ้นสุดเหตุการณ์การเปลี่ยนแปลงคุณสามารถใช้วิธีการโพสต์เป็นคำตอบใน: ฉันจะทำให้ฟังก์ชันการเปลี่ยน CSS3 เป็นปกติในเบราว์เซอร์ได้อย่างไร .

หมายเหตุ: คำถามนี้ยังเกี่ยวข้องกับ: - เหตุการณ์การเปลี่ยน CSS3


2
นี่เป็นคำตอบที่สมบูรณ์กว่าคำตอบที่ยอมรับ ทำไมถึงไม่โหวตเพิ่มอีก
Wes

อย่าลืมที่จะเรียกtransitionEndedHandlerในtransitionEnded(หรือการเปลี่ยนแปลงtransitionEndedจากtransitionEndedHandlerในaddEventListenerและremoveEventListenerและโทรtransitionEndedในtransitionEndedHandler)
Miquel

ขอบคุณ @Miquel; คิดว่าฉันต้องการใช้เพียงแค่เมื่อฉันหมายถึงtransitionEnded transitionEndedHandler
Mark Rhodes

ฉันเชื่อว่าปัญหา Chromium สำหรับสิ่งนี้สามารถพบได้ที่นี่: code.google.com/p/chromium/issues/detail?id=388082แม้ว่าความคิดเห็นสุดท้ายดูเหมือนว่า (ไม่ถูกต้องในมุมมองของฉัน) จะลดราคาเป็นข้อบกพร่องดังนั้นจึงเป็นเช่นนั้น ปัจจุบันถูกทำเครื่องหมายว่า "จะไม่แก้ไข"
Willster

ไม่ต้องใช้ชื่ออื่นแล้ววันนี้caniuse.com/#feat=css-transitions
Juan Mendes

43

ฉันใช้รหัสต่อไปนี้ง่ายกว่าการพยายามตรวจหาเหตุการณ์สุดท้ายที่เบราว์เซอร์ใช้

$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', 
function() {
 //do something
});

หรือหากคุณใช้ bootstrap คุณก็สามารถทำได้

$(".myClass").one($.support.transition.end,
function() {
 //do something
});

เนื่องจากมีสิ่งต่อไปนี้ใน bootstrap.js

+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd',
      'MozTransition'    : 'transitionend',
      'OTransition'      : 'oTransitionEnd otransitionend',
      'transition'       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el = this
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()
  })

}(jQuery);

2
ซึ่งช้ากว่าเนื่องจากต้องค้นหารายการทั้งหมดทุกครั้งที่เกิดเหตุการณ์เพื่อดูว่าเหตุการณ์นั้นถูกต้องหรือไม่
phreakhead

3
@phreakhead การแสดงของแนวทางเหล่านี้จะคล้ายกันมาก
ทอม


5

สิ่งนี้สามารถทำได้อย่างง่ายดายด้วยtransitionendเอกสาร Event ดูที่นี่ ตัวอย่างง่ายๆ:

document.getElementById("button").addEventListener("transitionend", myEndFunction);

function myEndFunction() {
	this.innerHTML = "Transition event ended";
}
#button {transition: top 2s; position: relative; top: 0;}
<button id="button" onclick="this.style.top = '55px';">Click me to start animation</button>


1
นี่คือคำตอบที่ถูกต้องในปัจจุบันไม่จำเป็นต้องมีคำนำหน้าอีกต่อไป caniuse.com/#feat=css-transitions
Juan Mendes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.