JS点击按钮实现图片的无缝滚动-纯JS实现
js的无缝滚动有很多种,可以自动滚动,也可以手动点击滚动,这里介绍手动点击滚动。
为了方便演示这里代码中并没有用到图片。
实现思路:
首先要实现左右滚动,前提是一定空间下,元素显示不完需要滚动显示。
本例子首先外面的div设置为4个li的宽度,并将其设置为overflow: hidden;,防止子元素溢出。总共5,1,2,3,4,5.总共6个div,默认显示1,2,3,4,将div中的ul设置为绝对定位,left为一个负li的宽度,这样,无论向左滚动还是向右滚动都有元素备用。
如果向左滚动,先用定时器设置ul的left的值,当移动一个li宽度后结束定时器。然后移除ul中最后一个li,然后再获取现在ul中最后一个li并复制一份添加到ul的第一个元素, 由于一个li宽度250px,所以再将起始值设为-250px,这样li顺序就变为了4,5,1,2,3,4。向右移动同理。
代码解释:
1、getFirstElementChild和getLastElementChild。
因为FirstElementChild和LastElementChild有兼容性问题,所以在代码最下方封装函数进行了兼容性处理。
2、var interId2;
定义这个是为了在定时器内部清除定时器。
3、overflow: hidden;
ul元素太多,父元素设置overflow: hidden;可以防止子元素溢出
在线演示:无缝滚动
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 1000px;
height: 300px;
position: relative;
border: 1px solid black;
overflow: hidden;
}
ul {
margin: 0;
padding: 0;
position: absolute;
left: -250px;
width: 1500px;
}
li {
float: left;
width: 248px;
height: 290px;
background-color: #007ACC;
list-style: none;
margin-top: 5px;
color: white;
font-size: 28px;
border: 1px solid white;
z-index: -1;
}
.btn1 {
position: absolute;
left: 0;
top: 130px;
z-index: 100;
width: 30px;
height: 30px;
}
.btn2 {
position: absolute;
right: 0;
top: 130px;
z-index: 100;
width: 30px;
height: 30px;
}
</style>
</head>
<body>
<div class="box">
<button id="btn1" class="btn1"><</button>
<button id="btn2" class="btn2">></button>
<ul>
<li class="li1">5555555</li>
<li class="li1">1111111</li>
<li class="li1">222222222</li>
<li class="li1">3333333</li>
<li class="li1">4444444</li>
<li class="li1">5555555</li>
</ul>
</div>
<script>
// 获取页面元素
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var ul = document.querySelector("ul");
// 左侧距离
var leftVal = -250;
// 定时器
var interId2;
// 左侧按钮
btn1.onclick = function () {
// 清除定时器,防止多次点击
clearInterval(interId2);
// 开始滚动
interId2 = setInterval(function () {
// 每次向左移动5px
leftVal += 5;
// 设置ul距离左侧的距离left
ul.style.left = leftVal + "px";
// 滚动一格清除定时器
if (leftVal == 0) {
clearInterval(interId2);
// 向左滚动,先移除ul中最后一个li,然后再获取现在ul中最后一个li并复制一份添加到ul的第一个元素
// 由于一个li宽度250px,所以再将起始值设为-250px,
var lastEle = getLastElementChild(ul);
ul.removeChild(lastEle);
var firstEle = getFirstElementChild(ul);
var cloneEle = getLastElementChild(ul).cloneNode(true);
ul.insertBefore(cloneEle, firstEle);
leftVal = -250;
ul.style.left = leftVal + "px";
}
}, 20)
}
//右侧按钮
btn2.onclick = function () {
// 清除定时器,防止多次点击
clearInterval(interId2);
interId2 = setInterval(function () {
leftVal -= 5;
ul.style.left = leftVal + "px";
if (leftVal == -500) {
clearInterval(interId2);
// 右侧和左侧原理相同
var firstEle = getFirstElementChild(ul);
ul.removeChild(firstEle);
var cloneEle = getFirstElementChild(ul).cloneNode(true);
ul.appendChild(cloneEle);
leftVal = -250;
ul.style.left = leftVal + "px";
}
}, 20)
}
// firstElementChild兼容性处理
function getFirstElementChild(element) {
var node, nodes = element.childNodes,
i = 0;
while (node = nodes[i++]) {
if (node.nodeType === 1) {
return node;
}
}
return null;
}
// lastElementChild兼容性处理
function getLastElementChild(element) {
var node, nodes = element.childNodes,
i = nodes.length - 1;
while (node = nodes[i--]) {
if (node.nodeType === 1) {
return node;
}
}
return null;
}
</script>
</body>
</html>
五个li代码(有点闪动的小问题):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 1000px;
height: 300px;
position: relative;
border: 1px solid black;
overflow: hidden;
}
ul {
margin: 0;
padding: 0;
position: absolute;
left: 0px;
width: 1300px;
}
li {
float: left;
width: 248px;
height: 290px;
background-color: #007ACC;
list-style: none;
margin-top: 5px;
color: white;
font-size: 28px;
border: 1px solid white;
z-index: -1;
}
.btn1 {
position: absolute;
left: 0;
top: 130px;
z-index: 100;
width: 30px;
height: 30px;
}
.btn2 {
position: absolute;
right: 0;
top: 130px;
z-index: 100;
width: 30px;
height: 30px;
}
</style>
</head>
<body>
<div class="box">
<button id="btn1" class="btn1"><</button>
<button id="btn2" class="btn2">></button>
<ul>
<li class="li1">1111111</li>
<li class="li1">222222222</li>
<li class="li1">3333333</li>
<li class="li1">4444444</li>
<li class="li1">5555555</li>
</ul>
</div>
<script>
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var ul2 = document.querySelector("ul");
// 左侧距离
var leftVal = 0;
// 定时器
var interId2;
// 防止多次点击
var flag = 1;
// 左侧按钮
btn1.onclick = function () {
// 清除定时器,防止多次点击
clearInterval(interId2);
//判断定时器是否执行完毕,只有移除节点后再生成节点
if (flag === 1) {
var firstEle = getFirstElementChild(ul2);
// 先clone最后一个元素,然后插入li最前面
var cloneEle = getLastElementChild(ul2).cloneNode(true);
ul2.insertBefore(cloneEle, firstEle);
leftVal = -250;
}
interId2 = setInterval(function () {
// 定时器开始将flag设为0,防止再次点击生成元素
flag = 0;
// 每次向左移动5px
leftVal += 5;
ul2.style.left = leftVal + "px";
if (leftVal == 0) {
clearInterval(interId2);
flag = 1;
var lastEle = getLastElementChild(ul2);
// 移除最后一个元素
ul2.removeChild(lastEle);
leftVal = 0;
ul2.style.left = leftVal + "px";
}
}, 20)
}
//右侧按钮
btn2.onclick = function () {
// 清除定时器,防止多次点击
clearInterval(interId2);
interId2 = setInterval(function () {
leftVal -= 5;
ul2.style.left = leftVal + "px";
if (leftVal == -250) {
clearInterval(interId2);
var firstEle = getFirstElementChild(ul2);
var cloneEle = firstEle.cloneNode(true);
ul2.appendChild(cloneEle);
ul2.removeChild(firstEle);
leftVal = 0;
ul2.style.left = leftVal + "px";
}
}, 20)
}
// firstElementChild兼容性处理
function getFirstElementChild(element) {
var node, nodes = element.childNodes,
i = 0;
while (node = nodes[i++]) {
if (node.nodeType === 1) {
return node;
}
}
return null;
}
// lastElementChild兼容性处理
function getLastElementChild(element) {
var node, nodes = element.childNodes,
i = nodes.length - 1;
while (node = nodes[i--]) {
if (node.nodeType === 1) {
return node;
}
}
return null;
}
</script>
</body>
</html>
总结
刚开始只用了5个li,虽然也能实现这样的效果,但在向左滚动后添加元素设置left时页面会闪动,暂时不知道怎么解决,所以采用了这种写法。
为了方便复制代码所以并没有加入图片,只用了div实现效果。