<js>轮播图

一、静态版本(ES5写法)

OOA:轮播图 点击按钮切换图片

0.布局 可视区(r定位)>图片盒子(a定位)+按钮(a定位)

   0-1.设置可视区box 溢出隐藏

   0-2.设置放图片的大盒子imgbox,让图片浮动一行显示 (width宽度和left位置由js自动设定)

   0-3.把左右按钮定位到box上

   0-4.为了实现无缝轮播图,复制第一张图到最后,利用视觉欺骗效果,改变索引和位置实现

1.获取元素 设置默认索引 补全布局:图片大容器宽和位置

2.绑定点击事件

3.改变左右索引

   3-1.左按钮索引--,索引到第一个:强行跳转到倒数第二张,设置初始位置为倒数第一张

   3-2.右按钮索引++,索引到最后一个:强行跳转到第二张,设置位置为初始位置为0

4.改变imgbox的位置

(1)HTML部分

    <!-- 可视区 -->
    <div class="box">
        <!-- 图片盒子 -->
        <div class="imgbox">
            <img src="imgs/banner1.jpg" alt="">
            <img src="imgs/banner2.jpg" alt="">
            <img src="imgs/banner3.jpg" alt="">
            <img src="imgs/banner4.jpg" alt="">
            <img src="imgs/banner5.jpg" alt="">
            <img src="imgs/banner6.jpg" alt="">
            <img src="imgs/banner7.jpg" alt="">
            <!-- 把第一张复制到最后 利用视觉欺骗  -->
            <img src="imgs/banner1.jpg" alt="">
        </div>
        <div class="btns">
            <input type="button" id="left" value="&lt">
            <input type="button" id="right" value="&gt">
        </div>
    </div>

 (2)CSS部分

      /* 可视区 */ 
        .box {
            position: relative;
            width: 1000px;
            height: 300px;
            margin: 0 auto;
            overflow: hidden;
        }
        /* 图片盒子 width宽度和left位置js设置  */   
        .imgbox {
            position: absolute;
        }
        
        .imgbox img {
            width: 1000px;
            height: 300px;
            float: left;
        }
        
        .btns input {
            position: absolute;
            width: 40px;
            height: 40px;
            background: rgba(255, 255, 255, .5);
            font-size: 25px;
            border: none;
            top: 130px;
        }
        
        .btns input:active {
            background: rgba(97, 147, 255, 0.39);
            color: #fff;
        }
        
        #left {
            left: 0;
        }
        
        #right {
            right: 0;
        }

(3)JS部分

<!-- 引入缓冲动画move -->
<script src="../move.js"></script>
<script>
    function Banner(index) {
        // 1.获取元素 设置初始值
        this.left = document.getElementById("left");
        this.right = document.getElementById("right");
        this.imgbox = document.querySelector(".imgbox");
        this.imgs = this.imgbox.children;
        // 传参 可以改变默认显示哪一张图
        this.index = index;

        // 补全布局
        // 设置宽(有px) imgbox的宽=imgs数组长度(几个)*一个图的宽
        this.imgbox.style.width = this.imgs.length * this.imgs[0].offsetWidth + "px";
        // 设置默认第几张图显示 即imgbox往左移动的距离 负的
        this.imgbox.style.left = -this.index * this.imgs[0].offsetWidth + "px";

        // 执行2.执行绑定事件
        this.addEvent();
    }

    Banner.prototype = {
            // 内置属性 补上 指向自己
            constructor: Banner,
            // 2.绑定事件
            addEvent: function() {
                const that = this;
                // 左点击绑定
                this.left.onclick = function() {
                        // 注意:新函数内this的指向问题
                        // 执行3左索引
                        that.changeIndexLeft();
                    }
                    // 右点击绑定
                this.right.onclick = function() {
                    // 执行3右索引
                    that.changeIndexRight();
                }

            },
            // 3.获取索引
            // 左
            changeIndexLeft: function() {
                //假如到了第1张(index0),跳转到倒数第二张(length-2)
                if (this.index === 0) {
                    this.index = this.imgs.length - 2;
                    // 要站在最后一张图的位置(第1张的复制品)(length-1)
                    this.imgbox.style.left = -(this.index + 1) * this.imgs[0].offsetWidth + "px";
                } else {
                    this.index--;
                }
                // 执行5.改变imgbox的位置
                this.changePos();
            },
            // 右
            changeIndexRight: function() {
                // 为了实现无缝轮播,到最后一张图(第1张的复制品)的时候,直接跳到第二张图(index1);为了避免反向轮播,这张图的定位要在0(站在第0位)
                if (this.index === this.imgs.length - 1) {
                    // 跳到第二张图(index1)
                    this.index = 1;
                    // 站在第一张图的位置(index0)
                    this.imgbox.style.left = 0;
                } else {
                    this.index++;
                }

                // 执行5.改变imgbox的位置
                this.changePos();
            },
            // 4.改变位置
            changePos: function() {
                // 位置:imgbox往左移动的距离 负的
                // 第一张0 * -1000:0
                // 第二张1 * -1000:-1000
                // 第三张2 * -1000:-2000
                // 第四张3 * -1000:-3000
                // this.imgbox.style.left=-this.index*this.imgs[0].offsetWidth+"px";
                // 写成缓冲样式 (这里不用写px)
                move(this.imgbox, {
                    left: -this.index * this.imgs[0].offsetWidth
                })
            }
        }
    new Banner(0);
</script>

二、渲染版本(ES6写法)

(1)HTML部分

   <div class="box">
        <div class="imgbox">
            <img src="" alt="" title="">
        </div>
        <div class="btns">
            <input type="button" id="left" value="左">
            <input type="button" id="right" value="右">
        </div>
    </div>

(2)CSS部分

      .box {
            width: 1000px;
            height: 300px;
            margin: 0 auto;
            position: relative;
        }
        
        .imgbox {
            position: absolute;
        }
        
        .imgbox img {
            width: 1000px;
            height: 300px;
            float: left
        }
        
        .btns input {
            position: absolute;
            width: 40px;
            height: 40px;
            border: none;
            background: rgba(200, 200, 200, 0.5);
            top: 130px;
        }
        
        .btns input:active {
            background: #55f;
            color: #fff
        }
        
        #left {
            left: 0
        }
        
        #right {
            right: 0
        }

(3)JS部分

<!-- 引入ajax文件 -->
<script src="./ajax.js"></script>
<!-- 引入move -->
<script src="./move.js"></script>
<script>
    class Banner {
        constructor() {
            this.imgbox = document.querySelector(".imgbox");
            this.url = "http://localhost:3000/api"; //走数据请求
            this.index = 0;
            this.left = document.getElementById("left");
            this.right = document.getElementById("right");
            this.getData();
            this.addEvent();
        }

        // 3.绑定事件
        addEvent() {
            const that = this;
            this.left.onclick = function() {
                that.changeIndex(0);
            }
            this.right.onclick = function() {
                that.changeIndex(1);
            }
        }

        // 4.改变索引
        changeIndex(d) { //d表状态 0左1右
            if (d === 0) {
                if (this.index === 0) { //第0位 索引倒数二 位置倒数1
                    this.index = this.imgbox.children.length - 2;
                    this.imgbox.style.left = -(this.imgbox.children.length - 1) * this.imgbox.children[0].offsetWidth + "px";
                } else {
                    this.index--;
                }
            } else {
                if (this.index === this.imgbox.children.length - 1) { //最后位 索引1 位置0
                    this.index = 1;
                    this.imgbox.style.left = 0;
                } else {
                    this.index++;
                }
            }
            this.move();
        }

        // 6.运动
        move() {
            move(this.imgbox, {
                left: -this.index * this.imgbox.children[0].offsetWidth
            })
        }

        // 1.获取数据
        getData() {
            ajax({
                url: this.url,
                data: {
                    type: "getBanner"
                },
                success: res => {
                    // console.log(res); 请求后端数据先看是不是json 再解析
                    res = JSON.parse(res);
                    if (res.code === 1) {
                        // code为1表示成功,渲染页面
                        // 把res.data绑到this上,给rander使用, 不用传参减少耦合
                        this.data = res.data;
                        // 渲染页面
                        this.render();
                    }
                }
            })
        }

        // 2.渲染页面
        render() {
            // console.log(this.data);
            // 2-1.根据数据,拼接页面结构
            let str = "";
            for (let i = 0; i < this.data.length; i++) { //把所有图片拼接(按banner.json内格式写)
                str += `<img src="${this.data[i].src}" alt="${this.data[i].alt}" title="${this.data[i].title}">`
            }

            // 2-4.为了无缝轮播,添加第一张到最后
            const first = this.data[0];
            str += `<img src="${first.src}" alt="${first.alt}" title="${first.title}">`


            // 2-2.将拼接好的页面结构设置到指定容器(banner图的大容器)
            this.imgbox.innerHTML = str;
            // 2-3.完善布局 设置imgbox宽度(imgbox子元素个数*任意个宽度)
            this.imgbox.style.width = this.imgbox.children.length * this.imgbox.children[0].offsetWidth + "px";

        }

    }
    new Banner();
</script>

(4)服务器

const http = require("http");
const fs = require("fs");
const qs = require("querystring");
const url = require("url");

http.createServer((req, res) => {
    const urlObj = url.parse(req.url);
    // 服务器的根路由
    if (urlObj.pathname.includes("/api")) {
        dataHandle(req, res);
    } else {
        staticHandle(req, res);
    }
}).listen(3000, () => {
    console.log("服务器开启成功: http://localhost:3000");
})

// 数据请求
function dataHandle(req, res) {
    console.log(req.method);
    if (req.method === "GET") {
        const obj = url.parse(req.url, true).query;
        programHandle(req, res, obj);
    } else if (req.method === "POST") {
        let str = "";
        req.on("data", (d) => {
            str += d;
        })
        req.on("end", () => {
            const obj = qs.parse(str);
            programHandle(req, res, obj);
        })
    }
}

// 数据请求后功能处理
function programHandle(req, res, data) {
    // 功能路由:接收到数据之后,根据数据中携带的功能类型,决定执行那个具体的功能
    // data格式 {type:"getGoods",xx:xx,x:xxx}
    switch (data.type) {
        case "getBanner":
            getBanner(req, res, data);
            break;
    }
}
// 获取banner数据
function getBanner(req, res, data) {
    // 服务器先读取数据库banner.json的数据 
    // utf-8是把后端获取的buffer数据转成字符编码
    fs.readFile("./database/banner.json", "utf-8", (err, data) => { //data就是banner.json
        const obj = {};
        if (err) {
            obj.code = 0;
            obj.title = "数据查找失败";
            obj.data = []; //空数组 没读到数据
        } else {
            obj.code = 1;
            obj.title = "数据查找成功";
            obj.data = JSON.parse(data); //data是json 转字符保存下来,[{},{}..]
        }
        res.write(JSON.stringify(obj)); //obj转json传输给前端
        res.end();
    })
}
// 后端返回给前端的通用数据格式
// 失败:
//     {
//         code:0,   //状态0 失败
//         title:"数据请求失败了",
//         data:"not data"
//     }

// 成功:
//     {
//         code:1,
//         title:"恭喜,数据请求成功了",
//         data:json数据
//     }


// 静态资源
function staticHandle(req, res) {
    const urlObj = url.parse(req.url);
    fs.readFile("./www" + urlObj.pathname, (err, data) => {
        if (err) {
            res.write("Forbidden \n You don't have permission to access this resource.");
        } else {
            res.write(data);
        }
        res.end();
    })
}

(5)json文件

[{
    "title": "1",
    "alt": "1",
    "src": "./imgs/banner1.jpg"
}, {
    "title": "2",
    "alt": "2",
    "src": "./imgs/banner2.jpg"
}, {
    "title": "3",
    "alt": "3",
    "src": "./imgs/banner3.jpg"
}, {
    "title": "4",
    "alt": "4",
    "src": "./imgs/banner4.jpg"
}, {
    "title": "5",
    "alt": "5",
    "src": "./imgs/banner5.jpg"
}, {
    "title": "6",
    "alt": "6",
    "src": "./imgs/banner6.jpg"
}]

三、jq版本-轮播图插件(抽屉式实现无缝轮播)

(1)HTML部分

 <div class="banner1">
        <!-- <div class="imgbox">
            <img src="" alt="1">
            <img src="" alt="2">
            <img src="" alt="3">
            <img src="" alt="4">
        </div>
        <div class="btns">
            <input type="button" value="<" id="left">
            <input type="button" value=">" id="right">
        </div>
        <div class="list">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
        </div> -->
    </div>
    <div class="banner2"></div>

(2)CSS部分

     .banner1 {
            width: 1000px;
            height: 300px;
            margin: 0 auto;
            position: relative;
            /* overflow: hidden; */
        }
        
        .banner1 .imgbox {
            width: 1000px;
            height: 300px;
        }
        
        .banner1 .imgbox img {
            width: 1000px;
            height: 300px;
            position: absolute;
            left: 1000px;
            top: 0;
        }
        /* 第一个放在可视区,其余叠放在不可视区 */
        
        .banner1 .imgbox img:first-child {
            left: 0;
        }
        
        .banner1 .btns * {
            position: absolute;
            top: 130px;
            width: 40px;
            height: 40px;
            border: none;
            background: rgba(200, 200, 200, 0.6);
        }
        
        .banner1 #left {
            left: 0
        }
        
        .banner1 #right {
            right: 0
        }
        
        .banner1 .list {
            display: flex;
            background: rgba(200, 200, 200, 0.6);
            height: 30px;
            line-height: 30px;
            text-align: center;
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
        }
        
        .banner1 .list span {
            flex: 1;
            border-left: solid 1px #fff;
            border-right: solid 1px #fff;
            cursor: pointer
        }
        
        .banner1 .list span.active {
            background: red;
            color: #fff;
        }
        /* 第二套 */
        
        .banner2 {
            width: 500px;
            height: 150px;
            margin: 0 auto;
            position: relative;
            /* overflow: hidden; */
        }
        
        .banner2 .imgbox {
            width: 500px;
            height: 150px;
        }
        
        .banner2 .imgbox img {
            width: 500px;
            height: 150px;
            position: absolute;
            left: 500px;
            top: 0;
        }
        
        .banner2 .imgbox img:first-child {
            left: 0;
        }
        
        .banner2 .btns * {
            position: absolute;
            top: 60px;
            width: 30px;
            height: 30px;
            border: none;
            background: rgba(200, 200, 200, 0.6);
        }
        
        .banner2 #left {
            left: 0
        }
        
        .banner2 #right {
            right: 0
        }
        
        .banner2 .list {
            display: flex;
            background: rgba(200, 200, 200, 0.6);
            height: 30px;
            line-height: 30px;
            text-align: center;
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
        }
        
        .banner2 .list span {
            background: rgba(200, 200, 200, 0.6);
            border-left: solid 1px #fff;
            border-right: solid 1px #fff;
            cursor: pointer;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            justify-content: center;
        }
        
        .banner2 .list span.active {
            background: red;
            color: #fff;
        }

(3)JS部分

<script src="./jquery.js"></script>
<script src="./jquery.banner.js"></script>
<script>
    const imgs = [{
        "title": "1",
        "alt": "1",
        "src": "./imgs/banner1.jpg"
    }, {
        "title": "2",
        "alt": "2",
        "src": "./imgs/banner2.jpg"
    }, {
        "title": "3",
        "alt": "3",
        "src": "./imgs/banner3.jpg"
    }, {
        "title": "4",
        "alt": "4",
        "src": "./imgs/banner4.jpg"
    }, {
        "title": "5",
        "alt": "5",
        "src": "./imgs/banner5.jpg"
    }, {
        "title": "6",
        "alt": "6",
        "src": "./imgs/banner6.jpg"
    }, {
        "title": "7",
        "alt": "7",
        "src": "./imgs/banner7.jpg"
    }]

    $(".banner1").banner(imgs, {
        // 按钮
        btn: false,
        // 分页器
        list: true,
        // 自动播放
        autoPlay: true,
        index: 0,
        // 两张间隔时间
        delayTime: 2000,
        // 移动时间
        moveTime: 200
    });

    $(".banner2").banner(imgs, {
        // 按钮
        btn: true,
        // 分页器
        list: true,
        // 自动播放
        autoPlay: true,
        index: 4,
        // 两张间隔时间
        delayTime: 1000,
        // 移动时间
        moveTime: 150
    });
</script>

(4)JS部分-功能部分

// 匿名函数前后加分号,避免影响其他没加分号的代码
;
(function($) { //jquery私有化:$就是jQuery
    "use strict";

    // console.log($);
    // 不需要操作dom 全局
    // $.xxx = function() {
    //     console.log("自定义方法1");
    // }

    // $.extend({
    //     xxx: function() {
    //         console.log("自定义方法2");
    //     }
    // })

    // 需要操作dom 局部
    // $.fn.xxx = function() {
    //     console.log("自定义方法3");
    // }

    // $.fn.extend($.fn, {
    //     xxx: function() {
    //         console.log("自定义方法4");
    //     }
    // })

    // $.extend({
    //     xxx: function() {
    //         console.log("自定义方法5");
    //     }
    // })



    $.fn.banner = function(data, ops = {}) {
        // 1.处理参数
        let { btn = true, list = true, autoPlay = true, delayTime = 3000, moveTime = 300, index = 0, currentClass = "active" } = ops;

        // 出去img的索引 进入为index
        let prev;
        // 封装成函数 this要在外面拿到
        const that = this;
        // 2.根据数据,渲染页面结构
        init();

        function init() {
            // 遍历数据 图片结构拼接
            let str = "";
            $.each(data, (idx, val) => {
                    // console.log(val);
                    str += ` <img src="${val.src}" alt="${val.alt}" title="${val.title}">`;
                })
                // $(".banner1").banner(imgs,{}) 执行对象-> this获取-> $(".banner1")
                // 把拼接的图片数据img放入imgbox,再插入banner1中
            $("<div class='imgbox'>" + str + "</div>").appendTo(that);

        }
        // 3.左右按钮 有btn就是true 要按钮,没有就是不要
        if (btn) {
            // 左按钮插入btns(btns在banner1) 回到btns添加右按钮
            // 给btns的子元素左绑定事件 返回btns 绑定右事件
            $("<input type='button' id='left' value='<'>").appendTo($("<div class='btns'></div>").appendTo(this)).parent().append($("<input type='button' id='right' value='>'>")).children("#left").click(leftClick).end().children("#right").click(rightClick)

            // 左过程
            // console.log(prev, index);
            // 左 反方向 正负号改变
            // $(".imgbox").children().eq(prev).css({ left: 0 }).stop().animate({
            //     left: $(".imgbox").children().eq(0).width()
            // }).end().eq(index).css({
            //     left: -$(".imgbox").children().eq(0).width()
            // }).stop().animate({
            //     left: 0
            // })
            // 右过程
            // console.log(prev, index);
            // imgbox的子元素
            // 第prev往左出去 负一张图宽度 安全起见,出去也设置初始位置
            // 第index往左进入 添加动画到可视区(left0) 
            // 进入之前将图片设置在可视区右边(避免第二轮错误,第一轮图片都出到左边去了)
            // $(".imgbox").children().eq(prev).css({ left: 0 }).stop().animate({
            //     left: -$(".imgbox").children().eq(0).width()
            // }).end().eq(index).css({
            //     left: $(".imgbox").children().eq(0).width()
            // }).stop().animate({
            //     left: 0
            // })
        }
        // 左点击事件
        function leftClick() {
            if (index === 0) {
                index = data.length - 1;
                prev = 0
            } else {
                index--;
                prev = index + 1;
            }
            Move(prev, index, -1); //通过负正确定左右
        }
        // 右按钮的点击事件函数
        function rightClick() {
            // console.log("右");
            if (index === data.length - 1) { //最后一张,index为0
                index = 0;
                prev = data.length - 1
            } else {
                index++;
                prev = index - 1;
            }
            Move(prev, index, 1);
        }


        // 4.分页器切换轮播图
        if (list) {
            // 和图片创建差不多
            let str = "";
            $.each(data, idx => {
                    // console.log(val);
                    str += `<span>${idx}</span>`;
                })
                // $(".banner1").banner(imgs,{}) 执行对象-> this获取-> $(".banner1")
                // 放入list中,再插入banner1中,选择子对象 当前索引添加选中样式(currentClass传参 默认active)
                // 找所有span绑定点击事件
            $("<div class='list'>" + str + "</div>").appendTo(this).children("span").eq(index).addClass(currentClass).end().click(function() {
                // console.log(this); //jq的this指向被点击的元素
                // console.log($(this).index()); //点击事件中 jq的index方法(是原生this)

                //目前的index,点击的是$(this).index() 
                // 目前走,点击进,这次点的是下一次的上一次,执行完功能后,把索引设置为当前点击的索引
                // console.log(index, $(this).index());

                // 点击大于上一个索引 往左
                if ($(this).index() > index) {
                    Move(index, $(this).index(), 1);
                }
                if ($(this).index() < index) {
                    Move(index, $(this).index(), -1);

                }

                // 执行完功能后,把索引设置为当前点击的索引
                index = $(this).index();
            })
        }


        // 3.封装的运动 (左右按钮 分页) 
        // 不要直接写$(".imgbox")创建多个会有问题 从顶层开始找imgbox
        function Move(prev, next, d) { //上索引 下索引 正负
            that.children(".imgbox").children().eq(prev).css({ left: 0 }).stop().animate({
                    left: -that.children(".imgbox").children().eq(0).width() * d
                }, moveTime).end().eq(next).css({
                    left: that.children(".imgbox").children().eq(0).width() * d
                }).stop().animate({
                    left: 0
                }, moveTime)
                // 4.处理分页器的选择状态
                // list子元素 被选中的索引加样式 兄弟元素移出样式
            that.children(".list").children("span").eq(next).addClass(currentClass).siblings().removeClass(currentClass);
        }


        // 5.自动播放
        if (autoPlay) {
            let t = setInterval(() => {
                // trigger模拟事件执行$("#right").trigger("click"); 但没有按钮就无法执行 直接拿到点击的回调函数
                rightClick();
            }, delayTime);

            // 鼠标移入banner 自动播放停止 this指向banner
            this.hover(function() {
                clearInterval(t);
            }, function() {
                t = setInterval(() => {
                    rightClick();
                }, delayTime);
            })
        }


    }
})(jQuery);

<html> <head> <meta charset="utf-8" /> <title>星星国际影城</title> <link href="css/index.css" rel="stylesheet" type="text/css" /> <script src="js/main.js" type="text/javascript"></script> </head> <body> <!--顶部--> <div id="header"> <div class="main"> <div class="info"> <a href=" " class="sina" title="sina" alt="新浪"></a > <a href="#" class="tqq" title="tqq" alt="tqq"></a > <a href="login.html" target="_blank">登录|</a > <a href="sign.html" target="_blank">注册|</a > <span>全国服务热线:888-8888888</span> </div> </div> </div> <!--logo部分--> <div id="logo"> <div class="logo_star"> <a href="index.html">< img src="images/logo.jpg" title="" alt="logo" /></a > </div> </div> <!--导航--> <div id="nav"> <div class="menu"> <!--导航菜单--> <ul> <li><a href="#" class="active">首页</a ></li> <li><a href="#">影片</a ></li> <li><a href="#">影城</a ></li> <li><a href="#">购票</a ></li> <li><a href="#">影城活动</a ></li> <li><a href="#">会员服务</a ></li> <li><a href="#">顾客互动</a ></li> </ul> <!--搜索框--> <div class="search"> <input type="text" placeholder="搜索影片" name="search"/> <input type="button" name="btn" value="" /> </div> </div> </div> <!--主体部分--> <div id="main"> <!--banner轮播图--> <div class="banner"> <ul class="main_content"> <li>< img src="images/b1.png" /></li> <li>< img src="images/b2.png" /></li> <li>< img src="images/b3.png" /></li> </ul> <!--轮播切换--> <ul class="tab"> <li></li> <li></li> <li></li> </ul> </div> <!--快速购票--> 在每行代码进行解释
06-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值