妙用 scale 與 transfrom-origin,精准控制動畫方向


上次發完 不可思議的純 CSS 導航欄下划線跟隨效果 這篇文章之后,很多朋友找我討論,感嘆 CSS 的奇妙。

然后昨天,群里一位朋友問到了一個和這個效果比較類似的效果,問如何

將下面這個動畫的下划線效果,從左進入,右邊離開修改為從上方進入,下方離開。

描述很難理解,看看原本的效果:

tsorigin

難點所在

第一眼看到這個效果,我的內心毫無波瀾。以為只是簡單的一個下划線 hover 效果,經過友人提醒,才發現,這個動畫效果中,下划線是從一端進入,從另外一端離開的。而且,這個 hover 動畫是純 CSS 實現的。

youqu

先不考慮上面說的修改需求,先想一想,如果就是還原上述效果,僅僅使用 CSS,該如何做呢?

 

還原效果

嗯,正常而言,我們一個 hover 效果,可能就是從哪里來,回哪里去,大部分的應該是這樣的:

xxx

現在,難點就在於如何在 hover 離開的時候,改變動畫行進的方向。

下面我們將一個 hover 動畫分解為 3 個部分:

  1. hover 進入狀態
  2. hover 停留狀態
  3. hover 離開狀態

但是,對於一個 hover 效果而言,正常來說,只有初始狀態,和hover狀態兩種。可能我們的代碼是這樣:

div {
    xxxx...
}

div:hover {
    xxxx...
}

對於一個 hover transition 動畫,它應該是從:

  • 正常狀態 -> hover狀態 -> 正常狀態 (三個步驟,兩種狀態)

所以,必須要有一種方法,能夠使得 hover 動畫的進入與離開產生兩種不一樣的效果,實現:

  • 狀態1 -> hover狀態 -> 狀態2 (三個步驟,三種狀態)

 

實現控制動畫方向的關鍵點

所以,這里的關鍵點就在於(划重點):

使得 hover 動畫的進入與離開產生兩種不一樣的效果 。

接下來,也就是本文的關鍵所在,使用 transform: scale() 以及 transform-origin 實現這個效果。

 

transform: scale() 實現線條運動

transform: scale 大家應該都很熟悉了,通俗來說是用於縮放,用官方的話說,就是:

CSS 函數 scale() 用於修改元素的大小。可以通過向量形式定義的縮放值來放大或縮小元素,同時可以在不同的方向設置不同的縮放值。

這里我們使用 transform: scaleX(0) 與 transform: scaleX(1) 來改變線條的顯示與隱藏,它的 CSS 代碼簡單來看,可能是這樣:

div {
    position: absolute;
    width: 200px;
    height: 60px;
}

div::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 200px;
    height: 2px;
    background: deeppink;
    transition: transform .5s;
    transform: scaleX(0);
}

div:hover::before {
    transform: scaleX(1);
}

scale

嗯?為什么是要用 transform: scale() 來實現線條的動畫?因為它可以配合 transform-origin 實現動畫的不同運動方向:

 

transform-origin 實現線條運動方向

transform-origin 讓我們可以更改一個元素變形(transform)的原點,transform-origin 屬性可以使用一個,兩個或三個值來指定,其中每個值都表示一個偏移量。 沒有明確定義的偏移將重置為其對應的初始值。

本效果最最最重要的地方就在於這里,我們使用 transform-origin 去改變 transform: scale() 的原點實現線條運動的方向。

  1. 我們給線條設置一個默認的 transform-origin 記為狀態1
  2. hover 的時候,設置另外一個不同的 transform-origin, 記為狀態2

所以,當然我們 hover 的時候,會讀取狀態2的transform-origin,從該原點開始放大至 scaleX(1),hover 離開的時候,會讀取狀態1的transform-origin,從scaleX(1)狀態縮小至該原點。

嗯,CSS代碼大概是這樣:

div {
    position: absolute;
    width: 200px;
    height: 60px;
}

div::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 200px;
    height: 2px;
    background: deeppink;
    transition: transform .5s;
    transform: scaleX(0);
    transform-origin: 100% 0;
}

div:hover::before {
    transform: scaleX(1);
    transform-origin: 0 0;
}

這里,我們巧妙的通過 hover 狀態施加了一層新的 transform-origin ,讓動畫的進入與離開產生了兩種不同的效果,兩個不同的方向。

如此一來,也就順利實現了我們想要的效果,撒花:

torigin

注意,這里使用了 transform-origin 去改變 transform: scale() 的原點實現線條運動的方向,而沒有借助諸如 position 位移,transform: translate(),或者 margin 等位置屬性去改變線條所在的位置。

所以,有趣的是,線條其實沒有產生過任何位移,這里其實也是障眼法,讓它看上去,它好像在移動。 

 

拓展延伸

嗯,有了上述方法,也就是 transform: scale() 配合 transform-origin ,我們可以開始隨意改變動畫的初始與結束狀態了。把他們運用到其他效果之上,簡單的幾個示意效果:

othertraorigin

 

值得注意的點

還有幾個點是比較有意思的,大家可以嘗試嘗試,思考思考:

  • 嘗試改變兩種狀態的 transition-timing-function 緩動函數,可以讓動畫更加流暢具有美感;
  • 注意一下,線條的 transition 設置的是 transition: transform .5s 而不是 transition: all .5s,體驗一下兩種寫法所產生的不同效果。

 

最后

本方法我個人最早見於 Css菜單懸停效果。如果你有更好的方法歡迎提出共同探討。

更多精彩 CSS 技術文章匯總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

好了,本文到此結束,希望對你有幫助 :)

如果還有什么疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=3ly2fi88twowo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM