已经2023年了,你还不会手撕轮播图?

jd.gif

目录

    • 一、前言
    • 二、动画基础
      • 1. 定时器
      • 2. left与offsetLeft
      • 3. 封装函数
        • 3.1 物体
        • 3.2 目标点
        • 3.3 回调函数
      • 4.封装
    • 三、基础结构
      • 3.1 焦点图
      • 3.2 按钮
      • 3.3 小圆点
      • 3.4 总结
    • 四、按钮显示
    • 五、圆点
      • 5.1 生成
      • 5.2 属性
      • 5.3 移动
    • 六、按钮
      • 6.1 准备
      • 6.2 出错
        • 6.2.1 小圆点跟随
        • 6.2.2 图片返回
      • 6.3 bug
    • 七、定时器
    • 八、总结


一、前言

目前,在移动端或是网页端对于轮播图的需求并不可少,我们有许多代替好的框架或者组件实现这个功能,但不如我们今天自己着手定制一个原生js轮播图,顺便总结提高一下相关知识点。

轮播图目前出现在各大购物网站的首页用来展示商品信息,现在也出了很多插件帮助我们更加便捷的实现多种多样的轮播图

京东

jd.gif

天猫

tm.webp

淘宝

tb.webp

纯手写轮播图对于初学者可能很难,也会有公司面试出轮播图来考察面试者的基础能力了。其实轮播图只要细分成几个小的模块逐步实现起来还是比较简单的。

下面,带大家来实现一下简易的轮播图

二、动画基础

我们都知道轮播图是有一个动画过程的,那如何封装实现这一个动画函数呢?

1. 定时器

前端的定时器有两种,一种是一次性定时器setTimeout,一种是重复性定时器setInterval

1-定时器.gif

如上图所示,setTimeout你只有点击一下按钮物体才会向前跑过了15ms就向前跑10px。而对于setInterval只需要点击一次便会每间隔15ms执行一次,页面中的倒计时效果也是这样做的。

所以,我们的轮播图肯定要选择setInterval第二种方案了。

2. left与offsetLeft

left就是我们加了定位的物体距离左侧的位置,这里可以参考一些常见的定位属性。

offsetLeft是一个只读属性(不能修改值),返回当前元素相对于 offsetParent 节点左边界的偏移像素值。当前父亲节点是整个页面,所以只需要把offsetLeft赋值给objectleft偏移量就行了。

3. 封装函数

有了定时器之后,我们就要考虑把这段代码封装成动画函数,想要的时候调用就行了。

封装函数要注意参数问题,那么我们定时器要传进来什么参数呢?

物体 目标点 回调函数

3.1 物体

物体为我们要移动的dom元素,就是上面哪个在屏幕行动的粉色盒子。

3.2 目标点

上面的盒子运动方向是有了,但是它一旦执行起来一个劲的向前冲,这也不行呀!

所以,我们试着修改一下上面的代码,比如让它到达800px就清楚定时器让它停下来,否则继续向前运动。
这时候我们只需要在定时器加了一个if else判断就行了。

if(object.offsetLeft==500){clearInterval(timer);
}
else{object.style.left=object.offsetLeft+10+'px';
}

2-target.gif

目标点满足了,但是还有两个疑问?

  • 到达800px后,如何后退?
  • 如何改变物体的运动曲线?

这两个问题只需要一个解决方案,只需要加一个step的变量,代表每一次移动的值代替固定的10px

这个变量只需要改成下面的公式计算就行:

var step = (target - obj.offsetLeft) / 10;

我们一开始的运动曲线是这样的,匀速状态:

liner.png

通过这样的公式既可以保证物体可以后退,又满足了先加速后减速的曲线运动

easeinout.png

这个公式如果仔细查看css的距离其实会有偏差的,比实际的目标点偏小,由于浮点数的计算问题,所以要使用公式,做近似处理。

step = step > 0 ? Math.ceil(step) : Math.floor(step);

3.3 回调函数

回调函数顾名思义当我调用这个定时器函数时,到达目标点了,定时器被清空了,就可以执行我传入的回调函数了。

下面让到达800px的物体,进行变色效果。

3-callback.gif

当然,后面也可以根据自己的要求实现特点的效果。

4.封装

我们把上面写好的代码统一到一个animate.js的文件中,需要的时候引入就行了。

function animate(obj, target, callback) {//排他原理clearInterval(obj.timer);obj.timer = setInterval(function () {//步长var step = (target - obj.offsetLeft) / 10;step = step > 0 ? Math.ceil(step) : Math.floor(step);if (obj.offsetLeft == target) {clearInterval(obj.timer);//回调函数callback && callback();}else {obj.style.left = obj.offsetLeft + step + 'px';}}, 15);
}

为了优化代码,防止用户过度点击,我们要在定时器执行的一开始通过排他原理预先清空之前的定时器,然后再执行我们自己的定时器。

三、基础结构

1.png

搭建html页面的结构其实很简单,我们主要把它分成三个部分,分别是中间的焦点图、左右两侧的按钮、底部的小圆点

3.1 焦点图

2.png

<ul class="rotate-middle"><li><a href="#"><img src="images/1.jpg" alt=""></a></li><li><a href="#"><img src="images/2.jpg" alt=""></a></li><li><a href="#"><img src="images/3.jpg" alt=""></a></li><li><a href="#"><img src="images/4.jpg" alt=""></a></li><li><a href="#"><img src="images/5.jpg" alt=""></a></li>
</ul>

焦点图在底部先定义一个400*300的盒子,盒子里面放入一张张的图片。这时候要注意每一个li加上浮动ul盒子的大小也需要伸长到足够容纳这一行排列图片的大小。

3.2 按钮

<button class="btn-lt">&lt;</button>
<button class="btn-rt">&gt;</button>

按钮我没采用字体图标伪元素之类的,直接粗暴的使用普通的< >了,样式就合适的更改就行了。

按钮额外要注意添加z-index提高位置,防止被图片压住了。

3.3 小圆点

<ol class="rotate-bottom"><li class="current"></li><li></li><li></li><li></li><li></li>
</ol>

底部小圆点现在我是直接在html里面写了,但是后面在js代码中会根据实际的图片数量实时更新。

3.4 总结

这三个基础的结构统一采用position定位(子绝父相),并且对于我们的ul也要加一个position: absolute;,因为后面要对这个盒子进行动画移动。

四、按钮显示

这部分我们的要求就是,让鼠标移动到图片的时候,按钮显示,离开不显示。正式写代码之前我们先来弄清楚一个问题?

  • mouseentermouseover有什么区别?

推荐文章:mouseenter与mouseover为何这般纠缠不清?

看完之后,选择mouseenter避免冒泡,获取时间源后,直接添加程序执行,按钮的隐藏还是显示直接使用display

focus.addEventListener('mouseenter', function () {lt.style.display = 'block';rt.style.display = 'block';});focus.addEventListener('mouseleave', function () {lt.style.display = 'none';rt.style.display = 'none';});

五、圆点

5.1 生成

for (var i = 0; i < ul.children.length; i++) {//创建ol livar cloneli = this.document.createElement('li');ol.appendChild(cloneli);
}

3.png

一开始,我们在html没给圆点,后面在js代码中根据图片的数量生成li

5.2 属性

 //自定义属性ol.children[i].setAttribute('index', i);

为了后面更好的移动轮播图,我们需要给每一个ol li定义一个属性index,这里我们是5张图片,index范围就是0~4

5.3 移动

//绑定事件
ol.children[i].addEventListener('click', function () {
// 排他原理for (var j = 0; j < ol.children.length; j++) {ol.children[j].className = '';}this.className = 'current';index = this.getAttribute('index');num = index;circle = index;animate(ul, -fixWidth * index);
})

4-move.gif

这时候,我们每点击一个圆点就获取它当前的index的值,然后调用动画函数传入目标值 ul 距离- 盒子的大小 * inddex,就可以移动图片了。

六、按钮

6.1 准备

左右两侧按钮移动本质上是一致的,我们先来做右侧按钮。预期目标是我每点击一次右侧按钮,图片就会向后移动一张。

那么这里我们还需要给每个图片也加上自定义属性吗?

其实不用,自定义一个变量num,随着点击的次数++就行了。

6.2 出错

5-btn.gif

如上面的图片一样,有几个问题:

  • 图片是动了,但是小圆点没动?
  • 到了最后一张图片,怎么返回?

下面,我们一个个解决。

6.2.1 小圆点跟随

小圆点跟随简单,我们也定义一个变量circle,当按钮每点击一次,circle++,然后让对应的圆点填充颜色就行了。

注意,这里和num我们要改善一下边界问题,到达最后一张图片是就不能继续++,要归零才行。

if (circle == 4) {circle = 0;
}
else {circle++;
}

6.2.2 图片返回

其实,当我们到达最后一张图片再点击是不连贯的,失去了平缓过度的效果。其实,我们可以在最后一张后面克隆第一张图片加上去。

当图片向后移动时,会过渡到最后一张(也就是第一张的克隆版本),这个时候再点击我们就快速回到第一张图片就行了。

//节点操作,复制照片
var cloneimg = ul.children[0].cloneNode(true);
ul.appendChild(cloneimg);

6.3 bug

6-bug.gif

如上图,我们点击圆点到达第三张图,然后点击右侧的按钮,没回到第四张图,为啥又退回了第二张图片。这主要是因为我们ol liindexnum cirle没同步导致的。

如何改善,很简单,把index实时赋值给num cirle就可以改善了。

左侧按钮,直接复制粘贴,改几个数值就行了,我不细讲了。

七、定时器

为了让轮播图按时移动,我们需要在最后加一个定时器效果,其实很简单,定时器内部直接调用右侧按钮的代码就行了。

var timer = this.setInterval(function () {rt.click();}, 1000);

7-rotate.gif

每次间隔一秒,图片向右移动一张,鼠标接触,停止轮播图,鼠标移开,继续轮播图。

八、总结

本篇文章主要实现了一个简易的轮播图效果,下次再见!

25.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/124960.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云端AI:释放企业创新力,打造智慧企业

文章目录 1. 云端AI的基本概念1.1 云计算1.2 人工智能1.3 云端AI 2. 云端AI的重要性2.1 成本效益2.2 弹性扩展2.3 无缝整合2.4 实时更新 3. 云端AI的应用领域3.1 智能客服3.2 预测分析3.3 自动化生产 4. 云端AI的未来趋势4.1 边缘计算与云端AI的融合4.2 可解释性AI4.3 隐私和安…

zabbix使用 -- 添加监控节点、自定义监控项、触发器

目录 页面中的一些概念配置agent服务来获取目标主机数据对nginx服务器进行监控在网页中添加一台配置 自定义监控项 -- 以监控nginx为例1、开启nginx本身的统计功能2、编写脚本采集数据3、在zabbix-server里获取数据监控ssh进程监控cron进程 触发器报警1、注册一个企业微信2、微…

开启全新教学模式!vLive虚拟直播如何赋能线上教培

&#xfeff; 如今&#xff0c;教培领域正在经历一场数字化的变革。随着科技的迅猛发展&#xff0c;教培形式也在不断演变&#xff0c;越来越多的企业和讲师开始采用虚拟直播来进行在线教学。那么&#xff0c;vLive虚拟直播https://live.vsochina.com/cnvLive虚拟直播是如何赋…

SpringBoot运维实用篇、打包、运行、高级配置、多环境开发、日志

文章目录 SpringBoot运维实用篇YW-1.SpringBoot程序的打包与运行程序打包程序运行SpringBoot程序打包失败处理命令行启动常见问题及解决方案SpringBoot项目快速启动&#xff08;Linux版&#xff09; YW-2.配置高级YW-2-1.临时属性设置YW-2-2.配置文件分类YW-2-3.自定义配置文件…

elasticsearch的数据聚合

聚合可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f; 这些手机的平均价格、最高价格、最低价格&#xff1f; 这些手机每月的销售情况如何&#xff1f; 实现这些统计功能的比数据库的sql要方便的多&#xff0c;而且…

下载安装包,安装 PySide2 到 windows 系统

20201206 修订&#xff1a;修改 PyCharm 中工具的配置描述 一、下载两个.whl 文件到本地&#xff0c; 可以在此下载 https://mirrors.tuna.tsinghua.edu.cn/ 我选用的是以下两个版本&#xff1a; shiboken2-5.15.2-5.15.2-cp35.cp36.cp37.cp38.cp39-none-win_amd64.whl …

vue three.js基本案例解析

1.安装依赖 // 比如安装148版本 npm install three0.148.0 --save2.使用页面引用 import * as THREE from three; // 引入扩展库OrbitControls.js import { OrbitControls } from three/addons/controls/OrbitControls.js; // 引入扩展库GLTFLoader.js import { GLTFLoader }…

攻防世界-WEB-NewsCenter

打开环境 有查询&#xff0c;猜测是sql注入 保存请求头到文件中 准备利用sqlmap 查找数据库 python sqlmap.py -r ./123.txt --dbs 查找表 python sqlmap.py -r ./123.txt --tables -D news 查找字段 python sqlmap.py -r ./123.txt --column -D news -T secret_table 显示字…

Spring整合tomcat的WebSocket详细逻辑(图解)

主要解决存在的疑问 为什么存在2种spring整合websocket的方式&#xff0c;一种是使用ServerEndpoint注解的方式&#xff0c;一种是使用EnableWebSocket注解的方式&#xff0c;这2种有什么区别和联系&#xff1f;可以共存吗&#xff1f;它们实现的原理是什么&#xff1f;它们的各…

华为数通方向HCIP-DataCom H12-821题库(单选题:321-340)

第321题 BGP的Open报文是用于建立对等体连接的,以下哪一项不属于Open报文中携带的参数信息? A、发送者的Router ID B、AS号 C、BGP版本号 D、TCP端口号 答案:D 解析:以下是BGP的Open报文: 第322题 在建立BGP对等体的过程中,OpenSent状态表明BGP等待的Open报文 并对收…

【Java基础篇 | 面向对象】—— 封装详解

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习Java的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、封装1.1什么是封装…

thinkphp6 入门(4)--数据库操作 增删改查

一、设计数据库表 比如我新建了一个数据库表&#xff0c;名为test 二、配置数据库连接信息 本地测试 直接在.env中修改&#xff0c;不用去config/database.php中修改 正式环境 三、增删改查 引入Db库 use think\facade\Db; 假设新增的控制器路径为 app\test\control…

【操作系统】聊聊Linux内存工作机制

内存主要是用来存储系统和应用程序的指令、数据、缓存等 内存映射 内存是需要安全机制保护的&#xff0c;所以只有内核才可以直接访问物理内存。进程如果要访问内存需要通过独立的虚拟地址空间。 虚拟地址空间其实包含两部分。一部分是内核空间&#xff0c;另一部分就是用户…

[C++网络协议] I/O复用

具有代表性的并发服务器端实现模型和方法&#xff1a; 多进程服务器&#xff1a;通过创建多个进程提供服务。 多路复用服务器&#xff1a;通过捆绑并统一管理I/O对象提供服务。✔ 多线程服务器&#xff1a;通过生成与客户端等量的线程提供服务。 目录 1. I/O复用 2. select函…

BMS电池管理系统——什么是BMS(一)

BMS电池管理系统 文章目录 BMS电池管理系统前言一、BMS是什么&#xff1f;二、BMS的主要功能模块1.采样及测量功能2.状态估计及预测功能3.控制及管理功能4.通讯和诊断功能 总结 前言 作为一名电气专业的学生&#xff0c;大学里学了很多嵌入式相关的知识&#xff0c;首先要明确…

Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

【前端】CSS-Grid网格布局

目录 一、grid布局是什么二、grid布局的属性三、容器属性1、display①、语句②、属性值 2、grid-template-columns属性、grid-template-rows属性①、定义②、属性值1&#xff09;、固定的列宽和行高2&#xff09;、repeat()函数3&#xff09;、auto-fill关键字4&#xff09;、f…

QT实现任意阶贝塞尔曲线绘制

bezier曲线在编程中的难点在于求取曲线的系数&#xff0c;如果系数确定了那么就可以用微小的直线段画出曲线。bezier曲线的系数也就是bernstein系数&#xff0c;此系数的性质可以自行百度&#xff0c;我们在这里是利用bernstein系数的递推性质求取&#xff1a; 简单举例 两个…

伪微分反馈控制(Pesudo-Drivative Feedback Control——PDF)

运动控制-单轴伺服控制带宽分析&#xff08;二&#xff09; - 知乎 (zhihu.com) 伪微分反馈控制_百度百科 (baidu.com) 伺服电机控制器的参数整定_老马过河hhh的博客-CSDN博客 伪微分PIIP控制_yukee10的博客-CSDN博客

【Linux成长史】Linux基本指令大全

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 数据库专栏 初阶数据结构 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如…