js商城项目——轮播图

本前端小白最近在学习js的基础知识,下面记录下一个轮播图的具体写法思路。

1、具体实现效果图



2、主要涉及知识要点

获取元素节点进行Dom事件操作
offset家族获取元素的宽高值
定时器的应用
缓动动画的封装

3、轮播图实现思路方法

1)获取需要的标签元素
// 1. 获取需要的标签
var casualContent = myTool.$('casual_content');
var contentImg = casualContent.children;
var casualControl  = myTool.$('casual_control');
var casualControlBottom = casualControl.children[2];

// 更改背景颜色(后面会用到先写着总是没错的)
var bgColorArr = ['#0037b5','#bd91ff', '#6e02ad', '#10358e', '#f38120'];
var lkCasual = myTool.$('lk_casual');
 lkCasual.style.backgroundColor = bgColorArr[0];
2)创建全局索引,记录当前图片的index值
// 2. 全局索引
var iNow = 0;
3) 动态创建下面的指示器
// 3. 动态创建下面的指示器(也就是那个圆点)
for (let index = 0; index < contentImg.length; index++) {
    var li = document.createElement('li');
    casualControlBottom.insertBefore(li, casualControlBottom.children[0]);

}
4)设置第一个选中
// 4. 让第一个指示器选中
casualControlBottom.children[0].className = 'current';
5) 让除了第一张幻灯片归位
// 5. 让除了第一张幻灯片归位
var scrollImgWidth = casualContent.offsetWidth;
console.log(scrollImgWidth);
for (let index = 1; index < contentImg.length; index++) {
    contentImg[index].style.left = scrollImgWidth + 'px';
    
}
6) 处理左右按钮点击和底部圆点鼠标进入切换图片
var cPrev = casualControl.children[0];
var cNext = casualControl.children[1];

// 点击左边
cPrev.addEventListener('click', function(){
    /**
     * 当前可视区域幻灯片快速右移
     * 下一张图片出现在可视区域左边
     * 让这张幻灯片做动画进入
     */
    myTool.buffer(contentImg[iNow], {'left': scrollImgWidth})
    iNow --;
    if(iNow < 0) {
        iNow = contentImg.length - 1;
    }
    contentImg[iNow].style.left = -scrollImgWidth + 'px';
    myTool.buffer(contentImg[iNow], {'left': 0});
    changeIndex();

    // 改变背景颜色
    lkCasual.style.backgroundColor = bgColorArr[iNow];
})
// 点击右边
cNext.addEventListener('click', function(){
    /**
     * 当前可视区域幻灯片快速左移
     * 下一张图片出现在可视区域右边
     * 让这张幻灯片做动画进入
     */
    myTool.buffer(contentImg[iNow], {'left': -scrollImgWidth})
    iNow ++;
    // 边界处理
    if(iNow > contentImg.length - 1) {
         iNow = 0;
    }
    console.log(contentImg.length,iNow);
    contentImg[iNow].style.left = scrollImgWidth + 'px';
    myTool.buffer(contentImg[iNow], {'left': 0});
    changeIndex();
    // 更换背景颜色
    lkCasual.style.backgroundColor = bgColorArr[iNow];
})
// 底部处理
for (let index = 0; index < casualControlBottom.children.length; index++) {
    // 取出单个li标签
    var bottomLi = casualControlBottom.children[index];
    // 监听鼠标进入
    (function(index){
        bottomLi.addEventListener('mouseover', function (ev) {
            /**
             * 对比索引
             *  鼠标进入大于当前索引相当于点击向右
             *  鼠标进入小于当前索引相当于点击向左
             * */ 
            if (index > iNow) {
                myTool.buffer(contentImg[iNow], {'left': -scrollImgWidth})
                contentImg[iNow].style.left = scrollImgWidth + 'px';    
            }else if(index < iNow){
                myTool.buffer(contentImg[iNow], {'left': scrollImgWidth})
                contentImg[iNow].style.left = -scrollImgWidth + 'px';
            }
            iNow = index;
            
            myTool.buffer(contentImg[iNow], {'left': 0});

            changeIndex();
            lkCasual.style.backgroundColor = bgColorArr[iNow];
        })
    })(index)   
}
7)切换索引下面圆点选中对应图片
// 7. 切换索引的方法
function changeIndex() {
    for (let index = 0; index < casualControlBottom.children.length; index++) {
        casualControlBottom.children[index].className = '';
        casualControlBottom.children[iNow].className = 'current';
    }
}
8)设置定时器
// 8. 设置定时器
var timeId = setInterval(function () {
    autoPlay();
}, 2000)

// 自动播放
function autoPlay() {
    myTool.buffer(contentImg[iNow], {'left': -scrollImgWidth})
    iNow ++;
    // 边界处理
    if(iNow > contentImg.length - 1) {
        iNow = 0;
    }
    console.log(contentImg.length,iNow);
    contentImg[iNow].style.left = scrollImgWidth + 'px';
    myTool.buffer(contentImg[iNow], {'left': 0});
    changeIndex();
    lkCasual.style.backgroundColor = bgColorArr[iNow];
}
9)设置和清除定时器

鼠标进入图片时清除定时器,鼠标移出图片时重启定时器

// 9. 设置和清除定时器
casualContent.parentNode.addEventListener('mouseover', function (evt) {
    clearInterval(timeId);
})

casualContent.parentNode.addEventListener('mouseout', function (evt) {
    // clearInterval(timeId);
    timeId = setInterval(autoPlay, 2000);
})

3、html布局代码

<div class="casual-center">
    <div class="casual-center-w">
        <div id="casual_content" class="content">
            <div class="content-img">
                <a href="#"><img src="images/casual01.jpg" alt=""></a>
            </div>
            <div class="content-img">
            <a href="#"><img src="images/casual02.jpg" alt=""></a>
            </div>
            <div class="content-img">
                <a href="#"><img src="images/casual03.jpg" alt=""></a>
            </div>
            <div class="content-img">
                <a href="#"><img src="images/casual04.jpg" alt=""></a>
            </div>
            <div class="content-img">
                <a href="#"><img src="images/casual05.jpg" alt=""></a>
            </div>
        </div>
        <div  id="casual_control"  class="control">
            <a href="javascript:;" class="c-prev">
                <i class="lk-left"></i>
            </a>
            <a href="javascript:;" class="c-next">
                <i class="lk-right"></i>
            </a>
            <ul class="c-bottom">
                <!-- js根据图片数量动态生成 -->
                <!-- <li class="current"></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li> -->
            </ul>
        </div>
    </div>
</div>

4、css样式

.casual-center {width: 100%;height: 44rem;float: left;}
.casual-center .casual-center-w {margin: 0 17rem 0 21rem; /*定位*/position: relative;overflow: hidden;}
.casual-center .casual-center-w .content { /*background-color: red;*/width: 100%;height: 44rem;}
.casual-center .casual-center-w .content .content-img{width: 100%; height: 100%;position: absolute;}
.casual-center .casual-center-w .content img {width: 100%;height: 100%;cursor: pointer;vertical-align: top;}
.casual-center .casual-center-w .control a {background-color: rgba(0, 0, 0, .4);position: absolute;top: 50%;transform: translateY(-50%);padding: 1rem 0.2rem;}
.casual-center .casual-center-w .control a:hover {background-color: rgba(0, 0, 0, .8);}
.casual-center .casual-center-w .control a.c-prev {left: 0;}
.casual-center .casual-center-w .control a.c-next {right: 0;}
.casual-center .casual-center-w .control a i {font-size: 3rem;}
.casual-center .casual-center-w .control .c-bottom {position: absolute;bottom: 2rem;left: 50%;transform: translateX(-50%);display: flex;}
.casual-center .casual-center-w .control .c-bottom li {width: 1.6rem;height: 1.6rem;background-color: #fff;margin: 0 0.3rem;border-radius: 50%;cursor: pointer;}
.casual-center .casual-center-w .control .c-bottom li.current {background-color: orange;}

5、完整js代码

window.addEventListener('load', function(ev){
    /************轮播图 **************/
    (function(){
        // 1. 获取需要的标签
        var casualContent = myTool.$('casual_content');
        var contentImg = casualContent.children;
        var casualControl  = myTool.$('casual_control');
        var casualControlBottom = casualControl.children[2];

        // 更改背景颜色
        var bgColorArr = ['#0037b5','#bd91ff', '#6e02ad', '#10358e', '#f38120'];
        var lkCasual = myTool.$('lk_casual');
        lkCasual.style.backgroundColor = bgColorArr[0];


        // 2. 全局索引
        var iNow = 0;

        // 3. 动态创建下面的指示器
        for (let index = 0; index < contentImg.length; index++) {
            var li = document.createElement('li');
            casualControlBottom.insertBefore(li, casualControlBottom.children[0]);

        }
        // 4. 让第一个选中
        casualControlBottom.children[0].className = 'current';

        // 5. 让除了第一张幻灯片归位
        var scrollImgWidth = casualContent.offsetWidth;
        console.log(scrollImgWidth);
        for (let index = 1; index < contentImg.length; index++) {
            contentImg[index].style.left = scrollImgWidth + 'px';
            
        }
        // 6. 处理左右按钮点击
        var cPrev = casualControl.children[0];
        var cNext = casualControl.children[1];

        // 点击左边
        cPrev.addEventListener('click', function(){
            /**
             * 当前可视区域幻灯片快速右移
             * 下一张图片出现在可视区域左边
             * 让这张幻灯片做动画进入
             */
            myTool.buffer(contentImg[iNow], {'left': scrollImgWidth})
            iNow --;
            if(iNow < 0) {
                iNow = contentImg.length - 1;
            }
            contentImg[iNow].style.left = -scrollImgWidth + 'px';
            myTool.buffer(contentImg[iNow], {'left': 0});
            changeIndex();

            // 改变背景颜色
            lkCasual.style.backgroundColor = bgColorArr[iNow];
        })

        // 点击右边
        cNext.addEventListener('click', function(){
            /**
             * 当前可视区域幻灯片快速左移
             * 下一张图片出现在可视区域右边
             * 让这张幻灯片做动画进入
             */
            autoPlay();
        })
        
        // 底部处理
        for (let index = 0; index < casualControlBottom.children.length; index++) {
            // 取出单个li标签
            var bottomLi = casualControlBottom.children[index];
            // 监听鼠标进入
            (function(index){
                bottomLi.addEventListener('mouseover', function (ev) {
                    /**
                     * 对比索引
                     *  鼠标进入大于当前索引相当于点击向右
                     *  鼠标进入小于当前索引相当于点击向左
                     * */ 
                    if (index > iNow) {
                        myTool.buffer(contentImg[iNow], {'left': -scrollImgWidth})
                        contentImg[iNow].style.left = scrollImgWidth + 'px';    
                    }else if(index < iNow){
                        myTool.buffer(contentImg[iNow], {'left': scrollImgWidth})
                        contentImg[iNow].style.left = -scrollImgWidth + 'px';
                    }
                    iNow = index;
                    
                    myTool.buffer(contentImg[iNow], {'left': 0});

                    changeIndex();
                    lkCasual.style.backgroundColor = bgColorArr[iNow];
                })
            })(index)
            
            
        }
        
        // 7. 切换索引
        function changeIndex() {
            for (let index = 0; index < casualControlBottom.children.length; index++) {
                casualControlBottom.children[index].className = '';
                casualControlBottom.children[iNow].className = 'current';
            }
        }

        // 8. 设置定时器
        var timeId = setInterval(function () {
            autoPlay();
        }, 2000)

        // 自动播放
        function autoPlay() {
            myTool.buffer(contentImg[iNow], {'left': -scrollImgWidth})
            iNow ++;
            // 边界处理
            if(iNow > contentImg.length - 1) {
                iNow = 0;
            }
            console.log(contentImg.length,iNow);
            contentImg[iNow].style.left = scrollImgWidth + 'px';
            myTool.buffer(contentImg[iNow], {'left': 0});
            changeIndex();
            lkCasual.style.backgroundColor = bgColorArr[iNow];
        }

        // 9. 设置和清除定时器
        casualContent.parentNode.addEventListener('mouseover', function (evt) {
            clearInterval(timeId);
        })

        casualContent.parentNode.addEventListener('mouseout', function (evt) {
            // clearInterval(timeId);
            timeId = setInterval(autoPlay, 2000);
        })
    })()
})

其中用到的myTool的方法

(function (w) {
    w.myTool = {
        $: function (id) {
            return typeof id === 'string' ? document.getElementById(id) : null;
        },
        /**
         * 
         * @param {String} obj 
         * @param {String} attr 
         */
        getStyleAttr: function (obj, attr) {
            if (obj.currentStyle) { // IE 和 opera
                return obj.currentStyle[attr];
            } else {
                return window.getComputedStyle(obj, null)[attr];
            }
        },
        changeCssStyle: function (eleObj, attr, value) {
            eleObj.style[attr] = value;
        },
        /**
         * 
         * @param {String} eleObj 
         * @param {JSON} json 
         * @param {Function} fn 
         */
        buffer: function (eleObj, json, fn) {
            // 1.1 先清后设
            clearInterval(eleObj.timer);
 
            // 1.2 定义变量
            var speed = 0, begin = 0, target = 0, flag = false;
 
            // 1.3 设置定时器
            eleObj.timer = setInterval(function () {
                // 标志 (标签的所有属性有没有执行完动画)
                flag = true;
                for(var key in json){
                    // 获取要做动画属性的初始值
                    if(json.hasOwnProperty(key)) {
                        if(key === 'opacity'){
                            begin = parseInt(myTool.getStyleAttr(eleObj, key) * 100) || 100;
                            target = parseInt(json[key]* 100);
                        }else {
                            begin = parseInt(myTool.getStyleAttr(eleObj, key)) || 0;
                            target = parseInt(json[key]);
                        }
     
                        // 2.3 求出步长
                        speed = (target - begin) * 0.2;
                        speed = (target > begin) ? Math.ceil(speed) : Math.floor(speed);
     
                        // 2.4  动起来
                       if(key === 'opacity'){
                           eleObj.style.opacity = (begin + speed) / 100;
                       }else {
                           eleObj.style[key] = begin + speed + 'px';
                       }
     
                        // 2.5 判断
                        if (begin !== target) {
                            flag = false;
                        }
                    }
                }
 
                // 1.4 清除定时器
                if(flag){
                    clearInterval(eleObj.timer);
                    // 开启另一组动画
                    /* if(fn){
                         fn();
                     }*/
                    fn && fn();
                }
            }, 60);
        }
    };
})(window);

以上写法思路来自网易云课堂【撩课-零基础玩转JavaScript】想要查看视频教程的童鞋可以自行去观看噢(●'◡'●)。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352