背景
页面中有多个表格,每个表格中均有一从右到左匀速移动的元素,随着元素移动需要在表格中增减数据,由于使用css3动画无法捕捉元素移动位置,所以这里采用js控制dom的写法
解决办法
最终代码放在文章的最后,各位看官可以跳过这里直接取用。
思路如下,首先我采用了scrollLeft+setInterval进行试验,发现使用scrollLeft只能让内部元素最右侧和外部元素左右侧重合就无法继续滚动了
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>滚动</title><style>* {margin: 0;padding: 0;}#wrapper {cursor: pointer;width: 600px;height: 200px;border: 1px solid pink;overflow: hidden;display: flex;margin: auto;}#list {display: flex;}#list {margin-left: 600px;}.item {width: 200px;height: 200px;flex-shrink: 0;text-align: center;line-height: 200px;}.item:nth-child(odd) {background: skyblue;}.item:nth-child(even) {background: yellow;}</style>
</head><body><!-- 外层盒子 --><div id="wrapper"><!-- 内部滚动盒子 --><div id="list"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div></div></div><script>window.onload = function () {let speed = 10;let tab = document.getElementById("wrapper");let tab1 = document.getElementById("list");function handleScroll() {if (tab1.offsetWidth - tab.scrollLeft <= 0) { clearInterval(timer) }else {tab.scrollLeft++;}}let timer = setInterval(handleScroll, speed);}</script>
</body></html>
于是我用translateX代替scrollLeft,发现成功了,内部元素可以从右至左滚动至完全消失
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>滚动</title><style>* {margin: 0;padding: 0;}#wrapper {cursor: pointer;width: 600px;height: 200px;border: 1px solid pink;overflow: hidden;display: flex;margin: auto;}#list {display: flex;}#list {margin-left: 600px;}.item {width: 200px;height: 200px;flex-shrink: 0;text-align: center;line-height: 200px;}.item:nth-child(odd) {background: skyblue;}.item:nth-child(even) {background: yellow;}</style>
</head><body><!-- 外层盒子 --><div id="wrapper"><!-- 内部滚动盒子 --><div id="list"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div></div></div><script>window.onload = function () {let speed = 10;let scrollLength = 0;let tab = document.getElementById("wrapper");let tab1 = document.getElementById("list");function handleScroll() {if (tab1.offsetWidth + tab.offsetWidth < scrollLength) {clearInterval(timer)}else {scrollLength = scrollLength + 1;tab1.style.transform = 'translateX(-' + scrollLength + 'px)';}}let timer = setInterval(handleScroll, speed);}</script>
</body></html>
但是上述方法还有一个问题就是,当前页面有多个滚动元素,即会有多个定时器,由于不断地重绘,导致了页面卡顿,造成了两个相同的滚动元素滚动速度不一致的问题,于是我使用requestAnimationFrame代替setInterval解决了问题
requestAnimationFrame 是一个浏览器提供的 API,用于在下一次重绘之前执行动画。它可以让浏览器在下一次重绘之前调用指定的函数更新动画。这个函数的主要优点是它可以自动匹配显示器的刷新率,从而实现更平滑的动画效果。
最终代码
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>滚动</title><style>* {margin: 0;padding: 0;}#wrapper {cursor: pointer;width: 600px;height: 200px;border: 1px solid pink;overflow: hidden;display: flex;margin: auto;}#list {display: flex;}#list {margin-left: 600px;}.item {width: 200px;height: 200px;flex-shrink: 0;text-align: center;line-height: 200px;}.item:nth-child(odd) {background: skyblue;}.item:nth-child(even) {background: yellow;}</style>
</head><body><!-- 外层盒子 --><div id="wrapper"><!-- 内部滚动盒子 --><div id="list"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div></div></div><script>window.onload = function () {let speed = 10;let scrollLength = 0;let tab = document.getElementById("wrapper");let tab1 = document.getElementById("list");function handleScroll() {if (tab1.offsetWidth + tab.offsetWidth > scrollLength) {scrollLength = scrollLength + 1;tab1.style.transform = 'translateX(-' + scrollLength + 'px)';requestAnimationFrame(handleScroll);}}requestAnimationFrame(handleScroll);}</script>
</body></html>