看到旭神博客上的一篇文章,關(guān)于iPhone X劉海發(fā)型設(shè)計和衍生的交互,其就是通過CSS3 Shapes實現(xiàn)元素滾動自動環(huán)繞iPhone X頭部劉海效果。這里我整理了一下,寫一個縮減版。
iPhone X的劉海發(fā)型和衍生的交互
首先先看一下微博上流傳的交互樣式。

可以看出此交互就是滾動頁面時,列表會環(huán)繞著iPhoneX的劉海排列。
實際上,CSS3里面針對這種特定形狀環(huán)繞的效果已經(jīng)支持很久了,CSS3 Shapes和CSS3 Regions都是可以實現(xiàn)的,只是我們接觸甚少。
CSS Shapes環(huán)繞iPhone X劉海簡易方法
這里就描述一種在技術(shù)上簡單易懂的解決方式。
實現(xiàn)原理
CSS Shapes中有個CSS屬性名為shape-outside,可以讓內(nèi)聯(lián)元素以不規(guī)則的形狀進(jìn)行外部排列,語法如下:
/* 函數(shù)值 */
shape-outside: circle();
shape-outside: ellipse();
shape-outside: inset(10px 10px 10px 10px);
shape-outside: polygon(10px 10px, 20px 20px, 30px 30px);
/* <url>值 */
shape-outside: url(image.png);
/* 漸變值 */
shape-outside: linear-gradient(45deg, rgba(255, 255, 255, 0) 150px, red 150px);
shape-outside屬性想要生效,本身需要是浮動float元素。
本demo效果實現(xiàn)的簡易方法就是使用shape-outside:url('image.png')屬性實現(xiàn)類似效果,image.png就是用來被環(huán)繞的圖片,相當(dāng)于iPhoneX的劉海設(shè)計,環(huán)繞與否是基于計算alpha通道決定,簡單來講,就是沿著圖片非透明區(qū)域環(huán)繞。
由于使用url()的形狀計算是基于圖片元素,和Shapes其他四個inset(),circle(),ellipse和polygon()這些基礎(chǔ)形狀方法的計算性質(zhì)不一樣,可以直接使用垂直方向的margin進(jìn)行偏移。
先來看下實現(xiàn)效果吧

細(xì)節(jié)說明
列表環(huán)繞的劉海圖片和實際在頁面顯示的劉海圖并非是一張圖片,為了讓劉海和列表文字之間留有空隙,要將url('liu-outside.png')中的 liu-outside.png圖片做實色填充處理,這里是填充了6像素。

代碼:
css代碼
*{
margin: 0;
padding: 0;
list-style: none;
}
.box{
max-width: 600px;
height: 380px;
border: 4px solid #000;
overflow: auto;
margin: auto;
}
.liuOutside{
float: left;
width: 30px;
height: 180px;
margin-top: 100px;
-webkit-shape-outside: url('./liu-outside.png');
shape-outside: url('./liu-outside.png');
transition: margin-top .15s;
}
.liuhai{
width: 24px;
height: 180px;
background: url("./liu.png") no-repeat left center;
margin-top: 100px;
position: absolute;
}
.scrollContent li{
border-bottom: 1px solid #ddd;
padding: 1em;
}
html代碼
<div class="box">
<i class="liuOutside"></i>
<i class="liuhai"></i>
<ul class="scrollContent">
<li>這個方法是比較簡單的</li>
<li>使用shape-outside url(image.png)語法</li>
<li>其中'image.png'就是用來被環(huán)繞的圖片</li>
<li>環(huán)繞與否是基于計算alpha通道決定</li>
<li>即沿著圖片非透明區(qū)域環(huán)繞</li>
<li>為了不至于列表靠的太近</li>
<li>shape的url圖片右側(cè)</li>
<li>刻意填充了6像素實色</li>
<li>現(xiàn)在看到的齊劉海</li>
<li>是覆蓋在上面的一張圖</li>
<li>實際生效的是后面浮動的shape</li>
<li>此功能的實現(xiàn)需要JS的配合</li>
<li>主要控制margin-top值</li>
<li>只能對內(nèi)聯(lián)信息進(jìn)行跟隨控制</li>
</ul>
</div>
js代碼
var liuOutside = document.querySelector(".liuOutside");
var box = document.querySelector(".box");
var outside = function() {
var scrollTop = box.scrollTop;
// 滾動偏移應(yīng)用在margin-top上
liuOutside.style.marginTop = (100 + scrollTop) + "px";
};
// 滾動時實時監(jiān)聽改變shape的形狀
box.addEventListener("scroll",outside);
outside();
Tips
1.效果的實現(xiàn)必須要js代碼的配合,否則會出現(xiàn)很難受的效果,如下:

2.還有一種實現(xiàn)方案就是shape-outside:polygon(),通過點坐標(biāo)勾勒出和齊劉海形狀相似的多邊形形狀,css代碼如下:
.liuOutside{
float: left;
shape-outside: polygon(0 0, 0 100px, 16px 104px, 30px 116px, 30px 264px, 16px 276px, 0 280px, 0 0);
}
應(yīng)該想到的是,既然方法換了,那么js代碼相應(yīng)的也需要作出改變:
box.addEventListener('scroll', function () {
var scrollTop = box.scrollTop;
// 滾動偏移應(yīng)用在shape-outside上
shape.style.shapeOutside = 'polygon(0 0, 0 '+ (100 + scrollTop) +'px, 16px '+ (104 + scrollTop) +'px, 30px '+ (116 + scrollTop) +'px, 30px '+ (264 + scrollTop) +'px, 16px '+ (276 + scrollTop) +'px, 0 '+ (280 + scrollTop) +'px, 0 0)';
});
此方法在確定環(huán)繞點時比較繁瑣。
3.附上用到的兩張劉海圖片


注:根據(jù)張鑫旭大牛的文章所寫,一起學(xué)習(xí)。