tabs
滚动的tabs
by BigFatK
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Tabs组件滚动动画(JS实现)</title>
</head>
<body>
<div class="app">
<div class="tabs">
<div class="tab active">C</div>
<div class="tab">C++</div>
<div class="tab">JavaScript</div>
<div class="tab">Java</div>
<div class="tab">Python</div>
<div class="tab">TypeScript</div>
<div class="tab">很长的不知道什么语言哈哈哈哈</div>
<div class="tab">Lisp</div>
<div class="tab">C++</div>
<div class="tab">JavaScript</div>
<div class="tab">Java</div>
<div class="tab">Python</div>
<div class="tab">TypeScript</div>
<div class="tab">很长的不知道什么语言哈哈哈哈</div>
<div class="tab">Lisp</div>
<div class="tab">C++</div>
<div class="tab">JavaScript</div>
<div class="tab">Java</div>
<div class="tab">Python</div>
<div class="tab">TypeScript</div>
<div class="tab">很长的不知道什么语言哈哈哈哈</div>
<div class="tab">Lisp</div>
</div>
</div>
</body>
</html>
CSS
* {
margin: 0;
padding: 0;
}
.tabs {
overflow: auto;
display: flex;
flex-flow: row nowrap;
background-color: yellow;
}
.tab {
white-space: nowrap;
padding: 10px 20px;
}
.tab.active {
color: red;
}
JavaScript
main()
function main () {
document.querySelector('.tabs').addEventListener('click', event => {
// 点击样式
const oldTab = document.querySelector('.active')
if (oldTab) oldTab.classList.remove('active')
const newTab = event.target
newTab.classList.add('active')
// 滚动到中间,需要先计算要滚动的距离`offset`
const rect = newTab.getBoundingClientRect()
const offset = rect.left + rect.width / 2 - window.innerWidth / 2
const tabs = document.querySelector('.tabs')
animateScroll(tabs, offset, 200)
})
}
// setInterval实现
// function animateScroll (el, offset, ms) {
// const interval = 16 // 每段的毫秒数(貌似不低于16ms?)
// const n = ms / interval // 分成的段数
// let i = 0
// const timerId = setInterval(() => {
// el.scrollLeft += offset / n
// ++i
// if (i >= n) clearInterval(timerId)
// }, interval)
// }
// requestAnimationFrame实现
function animateScroll (el, offset, ms) {
const n = ms / 16 // 帧数
let i = 0
const acc = offset / n // 每帧偏移量
function step () {
++i
el.scrollLeft += acc
if (i < n) {
requestAnimationFrame(step) // 还不够,就继续递归
}
}
requestAnimationFrame(step)
}