利用原生JS完成轮播图特效

原生JS轮播图

轮播图特效算是各大电商网站的必备特效之一,原理其实很简单,用到少量的知识点, DOM基础操作,计时器,对于新手难点就在于,图片滚动时的下方小圆点也要实现同步滚动,新手可以学习下,大佬欢迎指点!!话不多说 先上代码,样式的话这里就随便写写了, 不要在意那些细节,我们注重功能

HTML部分

<div id="container">
        <ul id="imgs">
            <li><a href="#"><img src="imgs/4.jpg">a>li>
            <li><a href="#"><img src="imgs/1.jpg">a>li>
            <li><a href="#"><img src="imgs/2.jpg">a>li>
            <li><a href="#"><img src="imgs/3.jpg">a>li>
            <li><a href="#"><img src="imgs/4.jpg">a>li>
            <li><a href="#"><img src="imgs/1.jpg">a>li>
        ul>
        <div id="pages">
            <i class="current">i>
            <i>i>
            <i>i>
            <i>i>
        div>
        <div id="prev"><div>
        <div id="next">>div>
    div>

CSS部分

<style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        #container {
            width: 590px;
            height: 470px;
            position: relative;
            margin: 50px auto;
            border: 1px solid #000;
            overflow: hidden;
        }
        ul {
            position: absolute;
            left : -590px;
            top: 0;
            width: 3540px;
            height: 470px;
        }
        #imgs li {
            width: 590px;
            height: 470px;
            list-style: none;
            float: left;
        }
        #pages {
            position: absolute;
            height: 30px;
            width: 100%;
            bottom: 0;
            background: #000;
        }
        #pages i {
            display: inline-block;
            width: 20px;
            height: 20px;
            margin: 5px;
            background: #fff;
            border-radius: 10px;
        }

        #pages i.current {
            background: #f00;
        }

        #prev, #next {
            width: 40px;
            height: 60px;
            background: #000;
            position: absolute;
            top: 0;
            bottom: 0;
            margin: auto;
            color: #fff;
            font-size: 30px;
            text-align: center;
            line-height: 60px;
        }
        #next {
            right: 0;
        }
    style>

结构样式 我觉得差不多就行了,而且也不是很丑啊,不信你看
利用原生JS完成轮播图特效_第1张图片

接下来是重点了,来我要开始表演了
JavaScript部分,实现三个功能
- 1.自动轮播切换图片(当然还有那种淡入淡出的轮播图,今天这里写位移的轮播图,我觉得更炫酷)
- -2. 点击左右箭头按钮也能前后切换图片,且鼠标滑入到banner图中后 图片的轮播效果要停止的,(不然何来用户体验)
- -3.鼠标滑入(或者点击)底部小圆点时,也能跳转到对应的图片,
- - 差不多也就这些效果了 来先看看JS代码热热身。
- (这里用到了自己封装的一个小的JS工具库(文章底部有代码),用到了
- 获取元素ID,设置CSS属性,及运动函数三个功能)

<script>
        var lis = $("li"), // 所有图片盒子
            length = lis.length, // 总图片张数
            ul = $("#imgs"), // 运动元素
            currentIndex = 1, // 当前索引
            nextIndex = 2, // 即将索引
            circles = $("i"), // 小圆点
            //为了防止运动函数计时器叠加 造成BUG
            isRunning = false; // true:正在执行切换动画   false:未执行切换动画

        // 轮播切换
        var move = function() {
            // 计算轮播过程中的定位
            var _left = -1 * nextIndex * 590;
            // 运动
            animate(ul, {left: _left}, 200, function(){
                if (nextIndex >= length) { // 向左
                    currentIndex = 1;
                    nextIndex = 2;
                    ul.style.left = "-590px";
                } else if (currentIndex <=  0) { // 向右
                    currentIndex = length - 2;
                    nextIndex = length - 1;
                    ul.style.left = -1 * (length - 2) * 590 + "px";
                }

                // 修改标记,可以继续切换
                isRunning = false;
            });
            // 小圆点样式
            // 找出变红色小圆点的索引
            var redIndex = nextIndex - 1;
            if (redIndex >= length - 2)
                redIndex = 0;
            else if(redIndex < 0)
                redIndex = length - 3;
            for(var i = 0; i < length - 2; i++) {
                circles[i].className = ""; //清空所有小圆点样式
            }
            circles[redIndex].className = "current";//鼠标进入的小圆点加上样式
            // 修改索引
            currentIndex = nextIndex;
            nextIndex++;
        }

        // 自动轮播
        var timer = setInterval(move, 3000); //开启定时器

        // 鼠标移入/移出容器
        $("#container").onmouseenter = function() {
            clearInterval(timer);
        }
        $("#container").onmouseleave = function() {
            timer = setInterval(move, 3000);
        }

        // 小圆点点击:事件委派
        $("#pages").onclick = function(e) {
            var src = e.target;
            if (src.nodeName === "I") {
                if (!isRunning) {
                    // 获取当前点击的小圆点在所有小圆点中的索引
                    var index = Array.from(circles).indexOf(src);
                    // 即将显示的图片索引
                    nextIndex = index + 1;
                    // 调用轮播切换函数
                    move();
                    // 修改标记,当前正在执行切换动画
                    isRunning = true;
                }
            }
        }

        // 向前
        $("#prev").onclick = function() {
            if (!isRunning) {
                nextIndex = currentIndex - 1;
                move();
                // 修改标记,当前正在执行切换动画
                isRunning = true;
            }
        }
        // 向后
        $("#next").onclick = function() {
            if (!isRunning) {
                move();
                // 修改标记,当前正在执行切换动画
                isRunning = true;
            }
        }

        $("#container").onselectstart = function(e){
            e.preventDefault();
        }
    script>

总结一下,
实现原理,轮播图片总计四张,当向右切换到最后一张的时候需要切换到第一张,但是 直接跳转第一张,太明显了,用户体验不好, 很多轮播图中基本都是 ,在第一张图之前克隆最后一张图,在最后一张图之后克隆第一张图,说到这 ,可能新手有点懵,这里给一张图 理解理解

利用原生JS完成轮播图特效_第2张图片

黑色框是原四张图 ,当走到第四张图的时候下一张还是第一张的图样,在最后一张图在做跳转,同样的图跳转的时候,肉眼是看不清的,这里也就实现了无缝轮播的原理!
这里偷了个懒 手动添加克隆的图片,也可以用JS代码生成
下面把刚才说的封装的小型JS库分享一下

//获取元素
function $(selector, context) {
    // 默认在 document 后代查找
    context = context || document;
    // 判断
    if (selector.indexOf("#") === 0) // id
        return document.getElementById(selector.slice(1));
    if (selector.indexOf(".") === 0) // className
        return byClass(selector.slice(1), context);
    // element
    return context.getElementsByTagName(selector);
}
**
 * 运动框架:线性运动
 * @param element 待添加运动动画效果的DOM元素
 * @param options 多属性运动配置选项
 * @param speed 限定运动的总时间
 * @param fn 运动结束后需要继续执行的函数
 */
function animate(element, options, speed, fn) {
    // 将在 element 元素上已有的运动动画效果停止
    clearInterval(element.timer);
    // 计算起始值、范围值
    var start = {}, range = {};
    for (var attr in options) {
        start[attr] = parseFloat(css(element, attr));
        range[attr] = options[attr] - start[attr];
    }
    // 记录运动开始时间
    var startTime = new Date().getTime();
    // 启动计时器,运动,将计时器id缓存在 element 上
    element.timer = setInterval(function(){
        // 计算实际运动时间
        var elapsed= Math.min(new Date().getTime() - startTime, speed);
        // 每个属性计算当前值
        for (var attr in options) {
            // 根据线性运动公式计算
            var result = elapsed * range[attr] / speed + start[attr];
            // 设置CSS
            element.style[attr] = result + (attr === "opacity" ? "" : "px");
        }
        // 判断是否停止计时器
        if (elapsed === speed) {
            // 停止计时器
            clearInterval(element.timer);
            // 如果有运动结束后执行的函数,则调用
            fn && fn();
        }
    }, 1000/60);
}

以上两个封装函数,通过这两个函数还可以改一下效果,淡入淡出的效果,
这里依赖annimate函数

* 运动框架:淡入
 * @param element 待添加运动动画效果的DOM元素
 * @param speed 限定运动的总时间
 * @param fn 运动结束后需要继续执行的函数
 */
function fadeIn(element, speed, fn) {
    element.style.display = "block";
    element.style.opacity = 0;
    animate(element, {opacity: 1}, speed, fn);
}

/**
 * 运动框架:淡出
 * @param element 待添加运动动画效果的DOM元素
 * @param speed 限定运动的总时间
 * @param fn 运动结束后需要继续执行的函数
 */
function fadeOut(element, speed, fn) {
    animate(element, {opacity: 0}, speed, function() {
        element.style.display = "none";
        fn && fn();
    });
}

后续待更新

你可能感兴趣的:(利用原生JS完成轮播图特效)