因需求關係,要求作到添加購物車時,有個小球從點擊添加的按鈕經過運動軌跡到達購物車位置, 由於是須要獲取動態位置, 經過css渲染動畫
愛莫能助, 很幸運的是, vue-transition內置組件提供js鉤子函數
, 爲我提供完成的動畫的保障javascript
首先, 讓咱們瞭解下vue transition的一些特性:css
Props:
name - string,用於自動生成 CSS 過渡類名。例如:name: 'fade' 將自動拓展爲.fade-enter,.fade-enter-active等。默認類名爲 "v"
appear - boolean,是否在初始渲染時使用過渡。默認爲 false。
css - boolean,是否使用 CSS 過渡類。默認爲 true。若是設置爲 false,將只經過組件事件觸發註冊的 JavaScript 鉤子。
type - string,指定過渡事件類型,偵聽過渡什麼時候結束。有效值爲 "transition" 和 "animation"。默認 Vue.js 將自動檢測出持續時間長的爲過渡事件類型。
mode - string,控制離開/進入的過渡時間序列。有效的模式有 "out-in" 和 "in-out";默認同時生效。
duration - number | { enter: number, leave: number } 指定過渡的持續時間。默認狀況下,Vue 會等待過渡所在根元素的第一個 transitionend 或 animationend 事件。
enter-class - string leave-class - string appear-class - string enter-to-class - string leave-to-class - string appear-to-class - string enter-active-class - string leave-active-class - string appear-active-class - string 事件: before-enter before-leave before-appear enter leave appear after-enter after-leave after-appear enter-cancelled leave-cancelled (v-show only) appear-cancelled 複製代碼
具體的一些使用方法,由於與本文內容不是很貼邊,在這裏不詳細講了 剩餘的就不在這裏說了, 開始主題html
不知道你們在寫原生js的時候,有沒有遇到過這樣的一個問題前端
一個DOM元素從display: none變爲display: block的時候,想要它想vue的transition同樣,利用動畫過渡過來, 你頗有可能會這麼寫vue
<div class="c-transition__container" style="display: none;"></div>
複製代碼
.c-transition__container {
width: 100px;
height: 100px;
background: red;
transition-duration: .5s;
transition-property: transform;
}
複製代碼
const oDiv = document.getElementsByClassName('c-transition__container')[0]
document.onclick = function() {
oDiv.style.transform = 'translate3d(100px, 0, 0)'
oDiv.style.display = 'block'
}
複製代碼
事實老是難以接受, 這麼寫是不會有平滑過渡的效果,而是直接在最終的位置顯示java
沮喪的你今後棄坑,發誓不再碰前端:laughing:web
彆着急, 下面講解如何實現從0到1的平滑
瀏覽器
首先咱們要了解瀏覽器的渲染時機
app
for(let i = 0; i < 100; i++) {
oDiv.style.transform = 'translate(100px, 0, 0)'
}
複製代碼
以上的for循環語句裏操做了100次的div, 但實際上瀏覽器並不會渲染100次, 根據上文函數
咱們能夠得知, 瀏覽器的UI Render是在每一個macroTask最後清空microTask隊列後纔會觸發一次, 可是瀏覽器會根據實際狀況來肯定是否須要渲染, 一般在每隔16.7ms的狀況下會渲染一次, 在此期間,瀏覽器會將全部的DOM操做推入到隊列
中,在進行渲染的時候會一個一個取出,直到清空隊列。
瀏覽器渲染過程:
JavaScript:JavaScript 實現動畫效果,DOM 元素操做等。(Cpu)
Style(計算樣式):肯定每一個 DOM 元素應該應用什麼 CSS 規則。(Cpu)
Layout(佈局):計算每一個 DOM 元素在最終屏幕上顯示的大小和位置。因爲 web 頁面的元素佈局是相對的,因此其中任意一個元素的位置發生變化,都會聯動的引發其餘元素髮生變化,這個過程叫 reflow。(每一個DOM對應一個渲染層)(Cpu)
Paint(繪製):在多個層上繪製 DOM 元素的的文字、顏色、圖像、邊框和陰影等, 這個過程叫作repaint。(Cpu)
Composite(渲染層合併):按照合理的順序合併圖層而後顯示到屏幕上。(進入GPU)(render Tree 解析渲染)
複製代碼
理解了以上部分, 那麼接下來的問題就好辦了
咱們逐句分析剛纔的案例:
translate(100px, 0, 0)
,而且更新了狀態display: block
, 注意這個時候, 也就是我剛纔提到的瀏覽器, 並無進行直接進行渲染,而是將它推入到了隊列裏, 但記得一句, DOM Tree是實時更新的, 此時雖然沒有渲染,可是DOM Tree裏的狀態已經更新了,這個時候DOM transform已經變成了100px, 當真正渲染的時候, 是從100px變爲100px,並非從0變成100px,因此咱們看到的是沒有過渡效果的。從以上的分析,咱們能夠基本瞭解爲何會是這種現象, 下面我來說下解決方案:
首先就是你們所熟知的setTimeout,這個的確能夠解決以上問題, 可是setTimeout屬於macroTask, 每一個task的最後都會觸發一次UI Render, 以上操做會形成屢次渲染, 因此並不推薦使用
(推薦) 強制瀏覽器清空隊列進行渲染操做
在獲取佈局信息操做的時候, 會強制瀏覽器清空隊列進行渲染, API有如下幾個: innerHeight、scrollTop、offsetHeight、getBoundingClientRect等等
這個時候, 瀏覽器從新進行迴流重繪渲染
操做, 這個時候觸發DOM操做均可以獲得有效回饋
Vue transitionjs鉤子函數其實就是原生js寫的動畫, 一樣從無到有進行平滑, 你學會了嗎?