2017-03-19 27 views
12

Üzerinde geçişler ayarlanmış bir svg var. Şimdi, bazı özelliklere sahip olan bir sınıf eklediğimde, geçiş yalnızca DOMContentLoaded olayı ve addclass olayı arasında gecikme eklediğimde gerçekleşir.Neden svg üzerinde geçişler DOMContent üzerinde çalışmıyor?

Gecikmesi Olmadan: Gecikme ile

! function() { 
 
    window.addEventListener('DOMContentLoaded', function() { 
 
    var logo2 = document.querySelector("svg"); 
 
    logo2.classList.add('start'); 
 
    }); 
 
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46"> 
 
      <defs> 
 
       <style> 
 
       polygon { 
 
        fill: red; 
 
        transition: opacity 3s ease-out, transform 3s ease-out; 
 
        opacity: 0; 
 
       } 
 

 
       .start polygon { 
 
       \t opacity: 1; 
 
       } 
 
\t \t \t \t 
 
\t \t \t \t #A1 polygon { 
 
\t \t \t \t \t transform: translate(100px, 100px); 
 
\t \t \t \t \t transition-delay: 1s; 
 
\t \t \t \t } 
 

 
\t \t \t \t /*styles after animation starts*/ 
 
\t \t \t \t .start #A1 polygon { 
 
\t \t \t \t \t transform: translate(0px, 0px); \t \t \t \t \t \t 
 
\t \t \t \t } 
 

 

 
      </style> 
 
      </defs> 
 
      <title>Logo</title> 
 
      <g id="A1"> 
 
       
 
       <polygon class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" /> 
 
      </g> 
 
      </svg>

:

! function() { 
 
    window.addEventListener('DOMContentLoaded', function() { 
 
    var logo2 = document.querySelector("svg"); 
 
    setTimeout(function(){ 
 
     logo2.classList.add('start'); 
 
    },0); 
 
    }); 
 
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46"> 
 
      <defs> 
 
       <style> 
 
\t     polygon { 
 
\t      fill: red; 
 
\t      transition: opacity 3s ease-out, transform 3s ease-out; 
 
\t      opacity: 0; 
 
\t     } 
 

 
\t     .start polygon { 
 
\t     \t opacity: 1; 
 
\t     } 
 
\t \t \t \t \t 
 
\t \t \t \t \t #A1 polygon { 
 
\t \t \t \t \t \t transform: translate(100px, 100px); 
 
\t \t \t \t \t \t transition-delay: 1s; 
 
\t \t \t \t \t } 
 

 
\t \t \t \t \t /*styles after animation starts*/ 
 
\t \t \t \t \t .start #A1 polygon { 
 
\t \t \t \t \t \t transform: translate(0px, 0px); \t \t \t \t \t \t 
 
\t \t \t \t \t } 
 

 

 
       </style> 
 
      </defs> 
 
      <title>Logo</title> 
 
      <g id="A1"> 
 
       
 
       <polygon class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" /> 
 
      </g> 
 
      </svg>

İşte bir infinitesmall gecikmeyle gecikme ikinci ilk iki örnektir

İkinci örnekte de gördüğünüz gibi, 0 saniyelik bir gecikme ekledim ama animasyonların çalışmasına neden oldu, neden?

Update1:

Ben DOMContentLoaded olmadan ve gecikmeksizin aynı kodu çalıştı :-) iyi ... hepimiz yanlış. Hala gecikmeden geçiş eklemek değildir:

! function() { 
 
    
 
    var logo2 = document.querySelector("svg"); 
 
    logo2.classList.add('start'); 
 

 
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46"> 
 
      <defs> 
 
       <style> 
 
       polygon { 
 
        fill: red; 
 
        transition: opacity 3s ease-out, transform 3s ease-out; 
 
        opacity: 0; 
 
       } 
 

 
       .start polygon { 
 
       \t opacity: 1; 
 
       } 
 
\t \t \t \t 
 
\t \t \t \t #A1 polygon { 
 
\t \t \t \t \t transform: translate(100px, 100px); 
 
\t \t \t \t \t transition-delay: 1s; 
 
\t \t \t \t } 
 

 
\t \t \t \t /*styles after animation starts*/ 
 
\t \t \t \t .start #A1 polygon { 
 
\t \t \t \t \t transform: translate(0px, 0px); \t \t \t \t \t \t 
 
\t \t \t \t } 
 

 

 
      </style> 
 
      </defs> 
 
      <title>Logo</title> 
 
      <g id="A1"> 
 
       
 
       <polygon class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" /> 
 
      </g> 
 
      </svg>

Ben de jQuery yeniden akışlara yol açmadığını kaydetti. CSSOM yüklenmeden önce hala ready işlevini tetiklemeyen inline jquery kodunun bir örneği. Dış jantlar olsaydı, satır içi jquery yerine CSSOM hazır olduktan sonra hazır olay ateşlenirdi. Ulaştığım anlayış, CSSOM'un, html dom'ın işlenmesinden sonra birkaç milisaniyeye ihtiyacı olmasıdır. Yani harici jquery indirir kadar CSSOM hazırdır. DOMContentLoaded sadece stil sayfalarının yüklenip yüklenmediği umurumda değil, CSSOM'un hazır olup olmadığını umursamıyor.

+0

'DOMContentLoaded' CSSOM' yapı' önce ateş şekline İlgili bir tartışma: http://stackoverflow.com/questions/42950574/are-deferred-scripts-executed-before-domcontentloaded-event – user31782

cevap

5

Bu, DOMContentLoaded'un yaptıklarından dolayı: DOM ayrıştırıldığında, ancak CSSOM'un (ve dolayısıyla stiller uygulanmadan önce) önce tetiklenir.

Eğer load olay beklemek istemiyorsanız ,
tek yön her belgenin elemana offsetXXX özelliği arayarak kuvvet senaryonuz yürütme (eşzamanlı) önce boyamak için tarayıcı, verilebilir (örneğin <body>):

! function() { 
 
    window.addEventListener('DOMContentLoaded', function(){ 
 
    document.body.offsetTop; // force a CSS repaint 
 
    var logo2 = document.querySelector("svg"); 
 
    logo2.classList.add('start'); 
 
    }); 
 
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46"> 
 
    <defs> 
 
    <style> 
 
     polygon { 
 
     fill: red; 
 
     transition: opacity 3s ease-out, transform 3s ease-out; 
 
     opacity: 0; 
 
     } 
 
     .start polygon { 
 
     opacity: 1; 
 
     } 
 
     #A1 polygon { 
 
     transform: translate(100px, 100px); 
 
     transition-delay: 1s; 
 
     } 
 
     /*styles after animation starts*/ 
 
     .start #A1 polygon { 
 
     transform: translate(0px, 0px); 
 
     } 
 
    </style> 
 
    </defs> 
 
    <title>Logo</title> 
 
    <g id="A1"> 
 
    <polygon class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" /> 
 
    </g> 
 
</svg>

+0

neden 'belgesi. body.offsetTop; 'bir relaint neden? – user31782

+0

Bu özellik, ofsetParent'in konumuna göre öğenin ofset konumunu döndürmesi gerektiğinden, bunu yapmak için bir reflow yapması gerekir, böylece herkesin bir konumu vardır. – Kaiido

+0

Daima DOMContentLoaded'in jQuery dom ile aynı olduğunu düşündüm. SO üzerine birçok mesaj bunu önerdi. CSSOM yüklendikten sonra ateş okuyor mu? – user31782

4

İkinci örnekte görebildiğiniz gibi 0 saniye gecikme ekledim ama animasyonların çalışmasına neden oldu, neden?CSS nesne modeli değil yüklenmiş yana

zaman DOMContentLoaded olay patlar

ilk HTML belgesi tümüyle dolu ve ayrıştırılan zaman DOMContentLoaded olay stil beklemeden tetiklenir, Yüklemeyi tamamlamak için görüntü ve alt çerçeveler. Çok farklı bir olay yükü yalnızca tam yüklü bir sayfayı algılamak için kullanılmalıdır. DOMContentLoaded'in çok daha fazla olması gerektiği yükü kullanmak inanılmaz bir popüler hatadır, bu yüzden dikkatli olun.

https://developer.mozilla.org/en/docs/Web/Events/DOMContentLoaded

Yani, css sınıfını ekleyerek animasyon yayınlanmaz.

setTimeOut yöntemi bir javascript olayıdır, bir kez tetiklendiğinde (0 zamanı bile olsa), geçerli tarayıcı yürütme sırasının sonuna eklenir (sizin durumunuzda CSS modelini yükledikten sonra eklenir). Bu nedenle animasyon düzgün bir şekilde ateşlenir.

Güncelleme:

Ama jquery domready yangınlar sonrasında CSSOM yüklenir. Yani tüm bu SO mesajlar teknik olarak yanlış?

domreadyDOMContentLoaded böylece teorik olarak konuşmak gerekirse, bunlar aynı şekilde davranır kullanır.

yüklenir CSSOM önce yürütülen komut dosyası etiketleri (satır içi veya dış) ertelenmiş musunuz? DOMContentLoaded ateş edilmeden önce erteleme özelliğiyle ertelenmiş

komut yürütülür. Yani cevabı evet.

+0

Şimdi birçok karışıklık var. 1. SO üzerinde birçok ileti, jquery domready öğesinin DOMContentLoaded ile aynı olduğunu önerir (ör. [This] (http://stackoverflow.com/a/8575961/3429430)) Ancak CSSOM yüklendikten sonra jquery hâlihazırda tetiklenir. Yani SO'daki bu mesajların hepsi teknik olarak yanlış mı? 2. CSSOM yüklenmeden önce ertelenmiş komut dosyası etiketleri (hem satır içi hem de harici) yürütüldü mü? – user31782

+0

lütfen kontrol edin – KAD

+0

Aşağıdaki kullanıcıyla tartıştığım gibi, JQuery hazır ve DOMContentLoaded gibi aynı şekilde diğer stackoverflow mesajları, prensip olarak doğru, ama jQuery olmadan bir tarayıcı yeniden boyamanız gerektiğinden bahsetmiş olmalılardı 'DOMContentLoaded '. Son bağlantınız CSSOM'dan bahsetmiyor. – user31782

İlgili konular