中心點靠近動畫解析
背景
今天要解析的是一種常見動畫效果,特點是:一排橫行排列的卡片,被激活的卡片盡可能移動到中間位置。我給它命名為【中心點靠近動畫】,先看下動畫效果:

解析
要實現(xiàn)動畫效果,個人總結(jié)有下面兩個核心點:
運動動畫基于什么實現(xiàn)? 每個卡片的運動到中心點的距離怎么計算?
1、運動動畫基于什么實現(xiàn)?
針對第一個問題比較好解決,大致可以分為兩種,一種是基于scrollLeft來控制卡片位置,一種是基于css3動畫屬性transform實現(xiàn)。兩種方式各有優(yōu)劣,具體如下:
scrollLeft
優(yōu)點:在實現(xiàn)點擊移動的效果下,能夠利用div的滾動特性,快速實現(xiàn)橫向滑動效果。
缺點:動畫性能較低。
transform
優(yōu)點:基于CSS3實現(xiàn),動畫性能高。
缺點:橫向滾動效果需要單獨實現(xiàn)。
這次是選用的transform實現(xiàn)的
html代碼
<div class="container">
<div class="list"
ref="listRef"
style={{transform: `translateX(${translateX}px)` }}
>
<div class="cardItem">1</div>
<div class="cardItem">2</div>
<div class="cardItem">3</div>
<div class="cardItem">4</div>
<div class="cardItem">5</div>
<div class="cardItem">6</div>
<div class="cardItem active">7</div>
<div class="cardItem">8</div>
</div>
</div>
.container {
position: relative;
overflow: hidden;
.list {
display: flex;
transition: 0.3s ease-in-out;
}
}
2、每個卡片的運動到中心點的距離怎么計算
這個問題是今天講的重點內(nèi)容,畫了一個簡潔的示意圖

每個卡片向中心點靠近時,list偏移的距離都是固定的。所以可以將list以中心點為分界線,分成兩個部分。
active卡片中心點距離list左邊距的距離為offsetLeft
如果 offsetLeft < w/2,也就是中心點的左側(cè)部分卡片,偏移距離translateX = 0;如果 offsetLeft > w/2,也就是中心點右側(cè)部分卡片,運動到中心點需要偏移dis=offsetLeft-w/2,但是需要檢查右邊隱藏部分內(nèi)容的寬度scrollRight,偏移距離需要為兩者之間的最小值Math.min(dis, scrollRight);
注意點:當(dāng)L < w時,也就是列表長度小于容器長度時,偏移距離都是0;
代碼如下:
// 其中cardW為卡片寬度
useEffect(() => {
const cardDomList = listRef.current?.children;
if (cardDomList) {
const leftDis = cardDomList[videoIndex].offsetLeft + cardW / 2;
const scrollRight = L > w ? L - w : 0;
if (leftDis < w / 2) {
setTranslateX(0);
} else {
const dis = leftDis - w / 2;
setTranslateX(-Math.min(dis, scrollRight));
}
}
}, [videoIndex]);
總結(jié)
解決方案整體是一個距離計算的算法,相對于之前計算方案,感覺這個計算方式更簡潔,具有通用性。
評論
圖片
表情
