2022年了,你还不会手撕轮播图?

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

一、前言

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

京东

网络异常,图片无法展示
|

天猫

网络异常,图片无法展示
|

淘宝

网络异常,图片无法展示
|

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

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

二、动画基础

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

1.  定时器

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

网络异常,图片无法展示
|

如上图所示,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';
}

网络异常,图片无法展示
|

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

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

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

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

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

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

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

3.3 回调函数

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

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

网络异常,图片无法展示
|

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

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);
}

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

三、基础结构

网络异常,图片无法展示
|

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

3.1  焦点图

网络异常,图片无法展示
|

<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 li
    var cloneli = this.document.createElement('li');
    ol.appendChild(cloneli);
}

网络异常,图片无法展示
|

一开始,我们在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);
})

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

六、按钮

6.1  准备

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

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

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

6.2 出错

网络异常,图片无法展示
|

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

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

下面,我们一个个解决。

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

网络异常,图片无法展示
|

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

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

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

七、定时器

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

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

网络异常,图片无法展示
|

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

八、总结


源码地址https://github.com/bosombaby/FED-small-projects


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

相关文章
|
SQL 监控 数据处理
SQL数据库数据修改操作详解
数据库是现代信息系统的重要组成部分,其中SQL(StructuredQueryLanguage)是管理和处理数据库的重要工具之一。在日常的业务运营过程中,数据的准确性和及时性对企业来说至关重要,这就需要掌握如何在数据库中正确地进行数据修改操作。本文将详细介绍在SQL数据库中如何修改数据,帮助读者更好
2072 4
|
9月前
|
编解码 API 开发工具
ModelScope魔搭25年2月版本发布月报
新春佳节的鞭炮声已经渐渐远去,在刚刚过去的一个月里,小鲸鱼给全球的开发者带来了一个不平凡的春节。DeepSeek-R1一系列开源模型的发布,给大家带来了惊喜和震动。所有人的热情,也给ModelScope社区带来了前所未见的巨大下载需求和流量,在这个月里,我们进行了数次紧急扩容和线上优化,尽量为大家提供更好的支持与服务。非常感谢大家的陪伴和理解,我们会持续进行平台优化和开源工具的建设,服务好整个开源社区。
372 9
|
传感器 数据采集 监控
基于阿里云MQTT服务,设计一个STM32的智能光伏控制系统
这篇文章详细介绍了利用STM32F103C8T6单片机实现光伏发电系统的关键技术。全文分为四章:第一章阐述了光伏发电的背景、意义及应用场景,强调其在绿色能源领域的重要性。第二章介绍了如何通过STM32F103C8T6及光敏电阻和伺服电机实现光线追踪系统,详细描述了硬件选择、连接及使用HAL库编写的单片机程序。第三章讲解了最大功率点追踪(MPPT)的原理,并展示了如何利用STM32F103C8T6和相关传感器、DC-DC转换器实现MPPT功能。第四章描述了如何通过STM32F103C8T6与SIM7600CE 4G模块连接到阿里云MQTT服务,实现设备状态数据的远程传输和控制。本文提供了全面的硬
18179 5
|
8月前
|
人工智能 智能设计 算法
中传广告学院x阿里云设计中心《通义高校百万创作人》AIGC宣传片共建校企合作实践平台
中传广告学院x阿里云设计中心《通义高校百万创作人》AIGC宣传片共建校企合作实践平台
|
Kubernetes Cloud Native 云计算
云原生技术深度解析:重塑企业IT架构的未来####
本文深入探讨了云原生技术的核心理念、关键技术组件及其对企业IT架构转型的深远影响。通过剖析Kubernetes、微服务、容器化等核心技术,本文揭示了云原生如何提升应用的灵活性、可扩展性和可维护性,助力企业在数字化转型中保持领先地位。 ####
|
供应链 安全 芯片
台积电7nm芯片断供影响分析:中国大陆半导体产业的挑战与机遇
近日,有关台积电可能断供中国大陆7nm芯片的消息引发了业界的广泛关注。这一事件不仅关系到全球半导体供应链的稳定性,也对中国大陆半导体产业的发展提出了新的挑战。本文将探讨这一事件背后的原因、可能的影响以及中国大陆半导体产业的应对策略。
664 0
|
安全 测试技术 Linux
浅谈黑客赚钱黑产
浅谈黑客赚钱黑产
LabVIEW创建自定义输入控件、显示控件和自定义类型2
LabVIEW创建自定义输入控件、显示控件和自定义类型2
655 2
|
机器学习/深度学习 人工智能 算法
主流AI服务——大专生新就业之路
主流AI服务——大专生新就业之路
584 0
|
域名解析 缓存 网络协议
DNS预解析和优化
DNS 的作用是将域名解析为 IP 地址,解析的过程是耗时的,转化后会做本地缓存,我们的优化的目标主要是针对用户第一次访问站点的时候陷入长时间白屏的问题。
434 1

热门文章

最新文章