背景
今天逛 CodePen,看到了這樣一個非常有意思的效果:
CodePen Demo -- Material Design Menu By Bennett Feely
這個效果還是有一些值得探討學習的點,下面我們一起來看看。
如何實現這樣一個類似的效果?
首先,想一想,如果讓你去實現上面的效果,你會怎麼做呢?
這裡我簡單羅列一些可能的辦法:
- 陰影 box-shadow
- 漸變 radial-gradient
- 縮放 transform: scale()
快速的一個一個過一下。
使用 box-shadow 實現
如果使用 box-shadow
,程式碼大致如下:
<div class="g-container">
<div class="g-item"></div>
</div>
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
}
.g-item {
position: absolute;
width: 48px;
height: 48px;
border-radius: 50%;
background: #fff;
top: 20px;
left: 20px;
box-shadow: 0 0 0 0 #fff;
transition: box-shadow .3s linear;
&:hover {
box-shadow: 0 0 0 420px #fff;
}
}
核心就在於:
- 外層一個設定了
overflow: hideen
的遮罩 - 內層元素 hover 的時候,實現一個
box-shadow: 0 0 0 0 #fff
到box-shadow: 0 0 0 420px #fff
的變化
效果如下:
整體的動畫是模擬出來了,但是它最致命的問題有兩個:
- 當我們的滑鼠離開圓形的時候,整個動畫就開始反向進行了,白色區域開始消失,如果我們要進行按鈕操作,是無法完成的
- 隱藏在動畫展開後的矩形內的元素,不容易放置
所以,box-shadow
看著雖好,但是隻能放棄。上述 Demo 的程式碼 -- CodePen Demo -- box-shadow zoom in animation
使用漸變 radial-gradient 實現
下面我們使用徑向漸變 radial-gradient
加上 CSS @property,也可以還原上述效果:
<div class="g-container"></div>
@property --size {
syntax: '<length>';
inherits: false;
initial-value: 24px;
}
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
background: radial-gradient(circle at 44px 44px, #fff 0, #fff var(--size), transparent var(--size), transparent 0);
transition: --size .3s linear;
&:hover {
--size: 450px;
}
}
我們通過控制徑向漸變的動畫效果,在 hover 的時候,讓原本只是一個小圓背景,變成一個大圓背景,效果如下:
emmm,效果確實是還原了,問題也很致命:
- 由於是背景的變化,所以滑鼠不需要 hover 到小圓上,只需要進入 div 的範圍,動畫就會開始,這顯然是不對的
- 和第一種
box-shadow
的方法類似,隱藏在白色之下的導航元素的 DOM 不好放置
上述 Demo 的程式碼 -- CodePen Demo -- radial-gradient zoom in animation
emmm,還有一種方法,通過縮放 transform: scale()
,也會存一定問題,這裡不繼續展開。
所以到這裡,想實現上述的效果,核心在於:
- 滑鼠要 hover 到圓上,才能開始動畫,並且,滑鼠可以在展開後的範圍內自由移動,且不會收回動畫效果
- 動畫展開後,裡面的 DOM 的放置,不能太麻煩,能不借助 Javascript 去控制裡面內容的顯示隱藏最好
利用 clip-path 實現動態區域裁剪
所以,這裡,我們其實是需要一個動態的區域裁剪。
在我的這篇文章中 -- 如何不使用 overflow: hidden 實現 overflow: hidden?,介紹了 CSS 中幾種裁剪元素的方式,而其中,最適合利用在這個效果的,就是 -- clip-path。
利用 clip-path
,可以非常好的實現,動態裁剪的功能,並且,程式碼也非常簡單:
<div class="g-container"></div>
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
transition: clip-path .3s linear;
clip-path: circle(20px at 44px 44px);
background: #fff;
&:hover {
clip-path: circle(460px at 44px 44px);
}
}
我們只需要利用 clip-path
,在最開始的時候,將一個矩形 div,利用 clip-path: circle(20px at 44px 44px)
裁剪成一個圓,當 hover 的時候,擴大裁剪圓的半徑到整個矩形範圍即可。
效果如下:
這樣,我們就能完美的實現題圖的效果,並且,內建的 DOM 元素,直接寫進這個 div 內部即可。
<div class="g-container">
<ul>
<li>11111</li>
<li>22222</li>
<li>33333</li>
<li>44444</li>
</ul>
</div>
效果如下:
CodePen Demo -- clip-path zoom in animation
很有意思的一個技巧,利用 clip-path 實現動態區域裁剪,希望大家能夠掌握。
最後
好了,本文到此結束,希望本文對你有所幫助 :)
想 Get 到最有意思的 CSS 資訊,千萬不要錯過我的公眾號 -- iCSS前端趣聞 ?
更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。