移动端常见的顶部菜单,让我们来实现一下把,效果图在下面。
html结构
<ul class="tab-container" id="tab-container">
<li>Movie</li>
<li>TV play</li>
<li>Anime</li>
<li>Qiyi</li>
<li>YouTube</li>
<li>Youku</li>
<li>Netflix</li>
<li>Video</li>
<li>Cartoon</li>
</ul>
JavaScript
const tabContainer = document.getElementById("tab-container");
const tabWidth = tabContainer.offsetWidth;
tabContainer.addEventListener("click", function (e) {
let tabItem = e.target;
// 计算当前点中的tabItem的中心到tab左顶点的长度(自己长度的一半加上它前面所有tabItem的长度)
let leftWidth = tabItem.offsetWidth / 2;
while (tabItem.previousElementSibling) {
tabItem = tabItem.previousElementSibling;
leftWidth += tabItem.offsetWidth;
}
if (leftWidth <= tabWidth / 2) {
tabContainer.scrollLeft = 0;
} else {
// 注意这里用clientWidth而不是offsetWidth
const maxDistance = tabContainer.scrollWidth - tabContainer.clientWidth;
const distance = leftWidth - tabWidth / 2;
// 左移有最大距离限制
tabContainer.scrollLeft = Math.min(maxDistance, distance);
}
});
到现在为止基本完成了,如下图。
(图片中间加了辅助线,方便观看)
如图,红点位置是box的一半。点击红点左边的tabItem,tab只需要左对齐,即设置scrolLeft为0。点击红点右边的tabItem,tab需要向左移动,移动的距离(例如点第四个tabItem,距离是c段)等于当前点击的tabItem的中心位置到box左边位置的距离减去box一半的长度。同时不能大于如图d的长度,不然右边会空出来。
加动画效果
现在来加上动画效果。使用requestAnimationFrame。
// 部分代码
if (leftWidth <= tabWidth / 2) {
const oldScrollLeft = tabContainer.scrollLeft;
let v = 0;
// 这时需要移动tab与box左对齐
if (oldScrollLeft > 0) {
const slide = function () {
v += vx;
let d = oldScrollLeft - v;
// 小于0时取0
tabContainer.scrollLeft = Math.max(d, 0);
if (tabContainer.scrollLeft > 0) {
requestAnimationFrame(slide);
}
};
requestAnimationFrame(slide);
}
}