我已經創建了簡單的演示,讓我們開始吧......
應該說,我們必須使用chrome和firefox進行比較
。演示1:
。block.addEventListener("click", ( ) => {
block.style.transform = "translateX(500px)"。
block.style.transition = ""。
block.style.transition = "transform 1s easy-in-out"。
block.style.transform = "translateX(100px)"。
});
.main {
width: 100px;
height: 100px;
background: orange;
}
< div id="block"/span> class="main"/span>> </div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
在這兩個瀏覽器中,我們不會看到任何變化
演示2: 。block.addEventListener("click", ( ) => {
block.style.transform = "translateX(500px)"。
block.style.transition = ""。
requestAnimationFrame(() => {
block.style.transition = "transform 1s easy-in-out"。
block.style.transform = "translateX(100px)"。
});
});
.main {
width: 100px;
height: 100px;
background: orange;
}
< div id="block"/span> class="main"/span>> </div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
在chrome中我們會看到影片,在firefox中我們會看到另一個東西。需要提及的是,火狐瀏覽器符合Jake Archibald in the Loop視頻的動作。但在chrome的情況下卻不是這樣。似乎firefox符合規范,但chrome不符合
。演示2(備用):
。block.addEventListener("mouseover", ( ) => {
block.style.transform = "translateX(500px)"。
block.style.transition = ""。
requestAnimationFrame(() => {
block.style.transition = "transform 1s easy-in-out"。
block.style.transform = "translateX(100px)"。
});
});
.main {
width: 100px;
height: 100px;
background: orange;
}
< div id="block"/span> class="main"/span>> </div>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
現在我們看到chrome可以正常作業,但firefox做的事情和chrome在Demo 2上做的一樣。他們的地方已經改變了 我還測驗了一些事件:mouseenter, mouseout, mouseover, mouseleave, mouseup, mousedown。最有趣的是,最后兩個事件在chrome和firefox中的效果是一樣的,而且它們都是不正確的,我想。
結論:似乎這兩個 UA 對事件的處理方式不同。但它們是如何做到的呢?
演示3
演示3: 在這里,我們看到firefox和chrome一樣好用,根據Archibald的說法,這就是預期的效果。但是你還記得演示2嗎,這兩個版本,為什么它們的行為如此不同?
uj5u.com熱心網友回復: TL;DR; 如果你想讓你的代碼在任何地方都作業得一樣,在你設定了你想要的初始值之后,自己強制進行回流。
你的問題是什么?
你在這里遇到的情況被稱為回流。我已經在其他答案中寫過了,但基本上這個回流是對頁面中所有方框的計算,需要確定如何繪制每個元素。
這種回流(又稱布局或重新計算)可能是一種昂貴的操作,因此瀏覽器在進行這種操作之前會盡可能地等待。
然而,何時發生這種情況并不是事件回圈規范的一部分。唯一的限制是,當ResizeObserver的通知被觸發時,重新計算已經完成。
盡管如果實施者愿意的話,他們完全可以在這之前完成這項作業(例如,Safari 將在其有一小段空閑時間時完成這項作業),或者我們甚至可以通過訪問一些確實需要更新布局的屬性來強制完成。 因此,在這個布局被重新計算之前,CSSOM甚至不會看到你傳遞給元素樣式的新值,它將像你確實同步地改變這些值一樣對待它,即它將忽略所有以前的值。
鑒于Firefox和Chrome都會等到最后一刻(在觸發ResizeObserver的通知之前)來觸發回流,我們確實可以期望在這些瀏覽器中,你的轉換會從初始位置開始( 那么在Chrome中會發生什么呢?我目前在手機上,無法進行廣泛的測驗,但我已經可以看到,罪魁禍首是設定過渡的那一行,先設定它將 "解決 "這個問題。
既然我必須做出猜測,那么我認為設定過渡可能會使元素切換其渲染路徑(例如從 CPU 渲染到 GPU 渲染),并且他們將強制進行回流操作。但這仍然只是一種猜測,沒有適當的測驗。最好的辦法是向https://crbug.com提出問題,因為這可能不是預期行為。 至于為什么你在不同的事件中擁有不同的行為,這可能是因為這些事件在不同的時刻啟動,例如,至少mousemove將被節流到繪畫幀,但我必須仔細檢查mousedown和mouseup。
標籤:block.addEventListener("click", ( ) => {
block.style.transform = "translateX(500px)"。
block.style.transition = ""。
requestAnimationFrame(() => {
requestAnimationFrame(() => {
block.style.transition = "transform 1s easy-in-out"。
block.style.transform = "translateX(100px)"。
});
});
});.main {
width: 100px;
height: 100px;
background: orange;
}
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
< div id="block"/span> class="main"/span>> </div> block.addEventListener("click", () => /span> {
block.style.transform = "translateX(500px)"。
block.style.transition = ""。
requestAnimationFrame(() => {
//如果你希望你的過渡從0開始
block.style.transform = "translateX(0px)"。
//強制回流。
document.body.offsetWidth;
block.style.transition = "transform 1s easy-in-out"。
block.style.transform = "translateX(100px)"。
});
});.main {
width: 100px;
height: 100px;
background: orange;
}
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
< div id="block"/span> class="main"/span>> </div>
translate(0)),中間的值會被忽略。但是,對于Safari來說,這又是不正確的。
block.addEventListener("click", ( ) => {
block.style.transform = "translateX(500px)"。
block.style.transition = "transform 1s easy-in-out"。
requestAnimationFrame(() => {
block.style.transform = "translateX(100px)";
});
});.main {
width: 100px;
height: 100px;
background: orange;
}
<iframe name="sif6" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
< div id="block"/span> class="main"/span>> </div>
