逐步手撕轮播图3(保姆级教程)
Posted 勇敢*牛牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逐步手撕轮播图3(保姆级教程)相关的知识,希望对你有一定的参考价值。
一、创建好基本样式:
初始化这个元素:
init()
:创建一个最大的div盒子。类名是carousel
,放在这个 body
里面。
- 然后在这个类名为
carousel
的div里面添加img-inco
(可以理解为图片条) - 再添加一个ul(根据数据的多少,生成li标签)
- 再添加两个左右按钮图片,其中特别注意类名书写和获取元素对象的顺序
此处的代码描述:
init();
/* 初始化 */
function init()
/* 创建最外层的大盒子 */
var carousel = document.createElement('div');
carousel.className = 'carousel';
/* 给这个盒子添加一个内容img-con和ul>li */
carousel.innerhtml=`
<div class='img-con'></div>
<ul>$arr.reduce(v=> v+'<li></li>','')</ul>
<img src='./img/left.png' class='left'>
<img src='./img/right.png' class='right'>
`
document.body.appendChild(carousel)
值得注意的是,这边全靠js生成html代码,难免会出现一些代码失误,最好就是开启控制台,边敲边看,是否成功的将数据渲染到页面上。
二、给所谓的这个滚动条,添加滚动块元素
首先这块: getImgBlock(data) 这个函数会将这个进去的数据,打包成一个div返回出来.那么咱们用这个函数,传入对应的数据,生成一个img-block盒子。
然后调用这个函数将在初始化的时候进行插入这个div就行。
初始后面紧跟着。
/* 获取这个盒子的对象 */
imgCon = document.querySelector('.img-con')
/* 给imgCon中插入一个div */
imgCon.appendChild(getImgBlock(arr[1]))
function getImgBlock(data)
if(blockList[data.id]) return blockList[data.id];
/* 创建一个div元素,用来包裹一些内容 */
var div = document.createElement('div');
/* 给这个div添加样式img-block样式 */
div.className = 'img-block';
/* 根据数据添加内容, */
div.innerHTML = `
<img src='$data.img'>
<div>
<!--这里的日期用正则分割-->
<!--用这个字符串的斜杠分割成字符串数组,并获取第一个元素-->
<span><i>$data.date.split('/').shift()</i>$data.date.match(/\\/.*/)[0].replace(/\\/(?=\\d+)/,".")</span>
<h1>$data.info</h1>
`
/*将创建好的div用id存储在存储对象中,那在此之前就是这个是需要定义一个对象*/
blockList[data.id] = div;
/*返回这个div*/
return div;
到这就做完了这个基本的布局;
第二小块 给最大的容器添加事件侦听,判断要到那个方向去,图片往那个方向移动 如果点击右,图片就得往左走 如果点击左箭头,图片就给往右走 pos就是定位到底选择那张图片的定位。
图片往左
if(--pos<0) pos = arr.length-1
图片往右
if(++pos>arr.length-1) pos = 0
那么点击圆点的话,就得判断是否点击了哪个li
;
var index = Array.from(e.target.parentElement.children).indexOf(e.target);
console.log(index);
判断下一次图片运行的方向
if(pos == index) return
/* 否则判断,direction的方向 */
/* 如果index大于pos,说明需要选择右边的图片,那图片移动的方向就是向左 */
direction = index>pos ? LEFT:RIGHT
/* 并且把index给pos */
pos = index;
切换小圆点背景色;
这个imgCon.nextElementSibling
就是ul
function changePrev()
if(prev)
prev.style.backgroundColor = 'transparent'
prev = imgCon.nextElementSibling.children[pos]
prev.style.backgroundColor = 'red';
致此就完成了第二部分第二小块、
/* 消除魔术字符串 */
const LEFT = Symbol('LEFT'),RIGHT = Symbol('RIGHT');
var arr=[
id:1001,img:"./img/a.jpg",date:"28/Jul/2022",info:"与父母的47天自驾游|向疆而行2万里,我们依旧是过客",
id:1002,img:"./img/b.jpg",date:"27/Jul/2022",info:"自驾川西小环线,在千碉之国遇见梨花如雪的季节",
id:1003,img:"./img/c.jpg",date:"26/Jul/2022",info:"被误解的沙县,原来有这么多美食只有在当地才能吃到!",
id:1004,img:"./img/d.jpg",date:"25/Jul/2022",info:"周末出逃计划 | 打卡美丽中国",
id:1005,img:"./img/e.jpg",date:"24/Jul/2022",info:"寻迹山川湖海,邂逅云南的冬与夏",
],
blockList= ,//存储创建的img-block
pos = 0,//默认第一张图片
prev,//选择设置背景色元素对象
direction = LEFT;//图片往那个方向移动:默认点击右按钮朝左走
var imgCon;//获取img-con这个盒子对象
init();
/* 初始化 */
function init()
/* 创建最外层的大盒子 */
var carousel = document.createElement('div');
carousel.className = 'carousel';
/* 给这个盒子添加一个内容img-con和ul>li */
carousel.innerHTML=`
<div class='img-con'></div>
<ul>$arr.reduce(v=> v+'<li></li>','')</ul>
<img src='./img/left.png' class='left'>
<img src='./img/right.png' class='right'>
`
/* 把盒子carousel渲染到页面上 */
document.body.appendChild(carousel)
/* 获取这个盒子里的img-con的对象 */
imgCon = document.querySelector('.img-con')
/* 给imgCon中插入一个div */
imgCon.appendChild(getImgBlock(arr[1]))
/* 给最外层的容器做事件委托点击,注意点击的是小圆点和左右标 */
carousel.addEventListener('click',clickHandler);
/* 初始化圆点背景色 */
changePrev()
/* 根据传进来的哪块的数据,创造一个块置元素赋值,并且返回 */
function getImgBlock(data)
if(blockList[data.id]) return blockList[data.id];
/* 创建一个div元素,用来包裹一些内容 */
var div = document.createElement('div');
/* 给这个div添加样式img-block样式 */
div.className = 'img-block';
/* 添加内容, */
div.innerHTML = `
<img src='$data.img'>
<div>
<!--这里的日期用正则分割-->
<!--用这个字符串的斜杠分割成字符串数组,并获取第一个元素-->
<span><i>$data.date.split('/').shift()</i>$data.date.match(/\\/.*/)[0].replace(/\\/(?=\\d+)/,".")</span>
<h1>$data.info</h1>
`
blockList[data.id] = div;
return div;
function clickHandler(e)
/* 如果被点击的对象不是LI,left,right就跳出 */
if(!/left|right/.test(e.target.className) && e.target.nodeName !== "LI") return
if(e.target.className =='left')
direction = RIGHT;/* 如果点击左按钮,图片往右移动 */
if(--pos<0) pos = arr.length-1 /* 如果pos小于0,pos定位到最右边 */
else if(e.target.className == 'right')
direction = LEFT;/* 如果点击右按钮,图片往左移动 */
if(++pos>arr.length-1) pos = 0;
else
/* 获取当前点击的li是ul的第几个 */
/* 找倒被点击的li的父容器ul的所有li。存在一个数组当中,然后查找这个li的下标 */
var index = Array.from(e.target.parentElement.children).indexOf(e.target);
/* 如果下标和当前的pos一致,那就跳出不执行跳转 */
if(pos == index) return
/* 否则判断,direction的方向 */
/* 如果index大于pos,说明需要选择右边的图片,那图片移动的方向就是向左 */
direction = index>pos ? LEFT:RIGHT
/* 并且把index给pos */
pos = index;
/* 触发事件改变背景色 */
changePrev()
/*改变元素颜色*/
function changePrev()
if(prev)
prev.style.backgroundColor = 'transparent'
prev = imgCon.nextElementSibling.children[pos]
prev.style.backgroundColor = 'red';
三、元素点击时无缝滚动
准备阶段:
我们的视口carousel的宽度是100vw,而iimgCon是200%,也就是说这个位置上能插入两张img—block
而当我点击符合的按钮之后,我就先得创建好这个下一张要移动的图片;
当direction方向向左时:
直接在imgcon尾部插入子元素,然后向左移动就会显示3号图片
当direction方向向右时:
图片得自左向右移动,当前的不能里面给立马挤掉,(当前还是这个原来的图片)
移动imgcon的left坐标x为当前的负一半;
function createNextImg()函数就这样的用法
/* 创建下一张图片 */
function createNextImg()
/* 判断当前图片需要移动的方向 */
if(direction === LEFT)
/* 将当前点击的要变化的索引对应的div获取插入在轮播容器的尾部 */
imgCon.appendChild(getImgBlock(arr[pos]));
/*imgCon容器坐标赋值*/
x=0;
else
/* 将当前点击的要变化的索引对应的div获取插入在轮播容器的子元素的前面 */
imgCon.insertBefore(getImgBlock(arr[pos]),imgCon.firstElementChild);
/* 并且重新设置轮播容器的位置 */
x= -imgCon.offsetWidth/2
/*重新设置轮播容器的位置*/
imgCon.style.left = x+'px'
/* 如果说图片创建好了 */
bool = true;
第二个就是得做好这个动画效果了
设置布尔值:false不进入 动画;
/* 执行图片向左的动画 */
function animation()
requestAnimationFrame(animation);
/*控制动画是否进入 */
if(!bool) return ;
/* 如果图片方向向左 轮播容器向左走*/
if(direction === LEFT)
/*控制动画移动速度 */
x -= speed;
/*如果x等于轮播图的一半就停止动画,并删除第一个子元素 */
if(x<=-imgCon.offsetWidth/2)
bool = false;
imgCon.firstElementChild.remove();
x = 0;
else
………………………………………………………………………………………………………………………………………………………………………………
四、动画设置
/* 执行动画 */
function animation()
requestAnimationFrame(animation);
/*控制动画是否进入 */
if(!bool) return ;
/* 如果图片方向向左 轮播容器向左走*/
if(direction === LEFT)
x -= speed;
/* 当向左移动到一半时 */
if(x<=-imgCon.offsetWidth/2)
bool = false;
/* 删除第一张图片,第二张掉在前面,这样 重新挪回到x=0的位置 */
imgCon.firstElementChild.remove();
x = 0;
else
/* 如果图片方向向右 轮播容器向右走*/
x += speed;
/* 当x等于0时停下来 */
if(x>=0)
bool = false;
/* 删除最后一个元素 */
imgCon.lastElementChild.remove();
x = 0;
/* 每次移动left形成动画 */
imgCon.style.left = x+'px'
至此完成了一个无缝的手动轮播图
无缝轮播图(数据驱动显示)
<!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>
body
margin: 0;
padding: 0;
.carousel
width: 100%;
height: 33.3vw;
position: relative;
left: 0;
top: 0;
font-size: 0;
min-width: 1000px;
overflow: hidden;
.carousel>.img-con
width: 200%;
height: 100%;
position: absolute;
left: 0;
.carousel .img-block
width: 50%;
height: 100%;
position: relative;
float: left;
.carousel .img-block>img
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
.carousel .img-block>div
position: absolute;
left:10vw;
top: 2vw;
font-size: 20px;
color: white;
.carousel .img-block>div>span>i
font-style:normal;
font-size: 28px;
.carousel .img-block>div>h1
font-size: 20px;
.clear::after
content: "";
display: block;
visibility: hidden;
height: 0;
overflow: hidden;
clear: both;
ul
list-style: none;
position: absolute;
bottom: 3vw;
left: 50%;
transform: translate(-50%,0);
ul li
width: 1.6vw;
height: 1.6vw;
border:2px solid red;
margin-left: 1.3vw;
float: left;
border-radius: 1.6vw;
.left,.right
position: absolute;
top: 50%;
transform: translate(0,-50%);
.left
left: 3vw;
.right
right: 3vw;
</style>
</head>
<body>
<script>
/* 消除魔术字符串 */
const LEFT = Symbol('LEFT'),RIGHT = Symbol('RIGHT');
var arr=[
id:1001,img:"./img/a.jpg",date:"28/Jul/2022",info:"与父母的47天自驾游|向疆而行2万里,我们依旧是过客",
id以上是关于逐步手撕轮播图3(保姆级教程)的主要内容,如果未能解决你的问题,请参考以下文章
[保姆级万字教程]打造最迷人的S曲线----带你从零手撕基于Huffman编码的文件压缩项目
[保姆级万字教程]打造最迷人的S曲线----带你从零手撕基于Huffman编码的文件压缩项目
[保姆级万字教程]打造最迷人的S曲线----带你从零手撕基于Huffman编码的文件压缩项目