前端学习之:轮播图

239 阅读5分钟

作一个ul列表结构的html

新建html,使用ul>li结构作图片容器:

    <style>
        :root {
            --img-w: 200px;
            --img-h: 200px;
        }

        body {
            margin: 0;
            padding: 0;
            width: 100vw;
        }

        .carousel {
            font-size: 0;
            width: calc(var(--img-w) * 3);
            position: relative;
            top: 100px;
            margin: 0 auto;

            border: 10px solid rebeccapurple;
            box-sizing: content-box;
            /*overflow: hidden;*/
        }

        .carousel ul {
            white-space: nowrap;
            margin: 0;
            padding: 0;
            list-style-type: none;
        }

        .carousel ul li {
            display: inline-block;
        }

        .carousel ul li img {
            display: inline-block;
            width: var(--img-w);
            height: var(--img-h);
            
            border: 1px solid red;
            box-sizing: border-box;
        }

    </style>

<body>
    <div id="app">
        <div class="carousel">
            <ul>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
            </ul>
        </div>
    </div>
</body>

image.png

  • 第一步,用ul>li结构作为多张img的容器,到时轮播图片的动画就以ul元素整体移动,如图中的红色边框。
  • 轮播需要只显示固定区域的画面,溢出的部分要hidden起来,所以外层套一个div.carousel,如图中的粗线边框。
  • 然后给div.carousel设置position属性后用margin: 0 auto魔法把整个轮播图整体居中为了方便看。
  • 因为li设置成inline流动布局所以white-space: nowrap;可以生效不让行内元素li换行。

通过整体一个div.carousel,里面放ul.li,li里面放img图片,就构成了最基本的轮播图片模型!

下面我们给这个模型设置动画

只需要加上动画my_translate并设置关键帧@keyframes:

.carousel ul {
    
    animation: my_translate 10s ease 1s infinite alternate;
}



@keyframes my_translate {
    from  {}
    16%   {translate: 0;}
    33%  {translate: calc(-1 * var(--img-w));}
    49%  {translate: calc(-2 * var(--img-w));}
    65% {translate: calc(-3 * var(--img-w));}
    81% {translate: calc(-4 * var(--img-w));}
    to  {translate: calc(-5 * var(--img-w));}
    /*100% {translate: calc(-6 * var(--img-w));}*/
    /*100% {translate: calc(-7 * var(--img-w));}*/
}

animation属性中第一个时间是整个动画的时间,第二个时间是延迟多久开始播放动画。

ease是每一帧动画的样式,表示首尾慢、中间快。

infinite表示播放无穷次。

alternate表示动画关键帧播放到to(100%)之后,倒过来播放,也就是一来一回为一次动画。

放开.carousel { overflow: hidden;}的注释后,效果如下:

IMG_1615.GIF

最后,我们来给li元素添加轮播图片进去

给img加上自适应宽高属性object-fitobject-position

        .carousel ul li img {
            
            
            object-fit: cover;
            object-position: center center;
        }

然后使用js动态加载图片的src

    const srcString ="'https://img2.baidu.com/it/u=421347826,2792415000&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img2.baidu.com/it/u=3123880262,455523890&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=4139606063,194286789&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=130504489,1044576680&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=2696759067,1221490204&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img1.baidu.com/it/u=1423197334,186448263&fm=253&fmt=auto&app=138&f=JPEG?w=491&h=492', " +
        "'https://img2.baidu.com/it/u=2391751777,1392423538&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img1.baidu.com/it/u=2241852295,652512022&fm=253&fmt=auto&app=138&f=JPEG?w=523&h=500'";
    const imgNodeList = document.querySelectorAll(".carousel ul li img");
    srcString.split(", ").forEach((src, index) => {
        console.log(src)
        imgNodeList[index].setAttribute("src", src.substring(1, src.length - 1));
    });

图片动画效果如下:

image.png

总结上面3步:

  1. 第一步,html里,用一个div,包裹住一个ul列表li里面放img
  2. 第二步,把li设置成行内inline元素,然后设置nowrap不给换行
  3. 第三步,给ul元素加动画animation,动画效果就是translate-x水平位移,看起来就像是轮播。
  4. 补充:这里的img.src是JavaScript动态加载
  5. 补充:其中font-size: 0; padding: 0;等其他不相关样式只是为了清除空白间隙。

最后,我们来美化轮播的样式效果

  • 设置图片的外边距:
:root {
    --img-w: 200px;
    --img-h: 200px;
    --img-m: 10px;
    --img-x: calc(var(--img-w) + var(--img-m) * 2);
}

如上,我们之前在:root中设置图片的宽度--img-w,现在在img样式中给每个img加上--img-m的外边距。

那么,包裹ul>li>img的外层div.carousel也需要调整能够展示3个img的宽度(高度自适应就可以)。这里我们算好一个img加上边距的宽度是--img-x,然后统一用这个单位来计算:

        .carousel ul li img {
            width: var(--img-w);
            height: var(--img-h);
            
            /* 左右边距 --img-m */
            margin: 15px var(--img-m);
        }
        
        .carousel {
        
            /* 外层div设置为3个img(包括左右边距)的总宽度 */
            width: calc(var(--img-x) * 3);
            
        }
        
        /*动画每一帧偏移宽度是img的整体宽度 */
        @keyframes my_translate {
            from  {}
            16%   {translate: 0;}
            33%  {translate: calc(-1 * var(--img-x));}
            49%  {translate: calc(-2 * var(--img-x));}
            65% {translate: calc(-3 * var(--img-x));}
            81% {translate: calc(-4 * var(--img-x));}
            to  {translate: calc(-5 * var(--img-x));}
            /*100% {translate: calc(-6 * var(--img-w));}*/
            /*100% {translate: calc(-7 * var(--img-w));}*/
        }
        
  • 修改div.carousel 和 img box-shadow模糊效果样式、边框效果
        .carousel {
        
            border: 10px inset rebeccapurple;
            
            box-shadow: 1px 1px 20px #999999;
        }
        
        .carousel ul li img {
        
            border: 5px outset gold;
            
            box-shadow: 1px 1px 10px dimgrey;
            
        }
        

如上,border: inset就是设置边框内嵌,outset是外凸的效果。

box-shadow设置盒子边框阴影效果。1px 1px代表阴影区域的x、y偏移,第三个px是阴影放大模糊度,最后一个是颜色。


好了,修改好之后效果如下: github.lwrong.com/carousel.ht…

附上整体代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=0.5"/>
    <meta name="keywords" content="轮播"/>
    <title>轮播图</title>
    <meta name="description" content="手写轮播图">
    <style>
        :root {
            --img-w: 200px;
            --img-h: 200px;
            --img-m: 10px;
            --img-x: calc(var(--img-w) + var(--img-m) * 2);
        }

        body {
            margin: 0;
            padding: 0;
            width: 100vw;
        }

        .carousel {
            font-size: 0;
            width: calc(var(--img-x) * 3);
            position: relative;
            top: 100px;
            margin: 0 auto;
            border: 10px inset rebeccapurple;
            box-shadow: 1px 1px 20px 5px #999999;
            overflow: hidden;
        }

        .carousel ul {
            white-space: nowrap;
            margin: 0;
            padding: 0;
            list-style-type: none;
            animation: my_translate 10s ease 1s infinite alternate;
        }


        @keyframes my_translate {
            from {
            }
            16% {
                translate: 0;
            }
            33% {
                translate: calc(-1 * var(--img-x));
            }
            49% {
                translate: calc(-2 * var(--img-x));
            }
            65% {
                translate: calc(-3 * var(--img-x));
            }
            81% {
                translate: calc(-4 * var(--img-x));
            }
            to {
                translate: calc(-5 * var(--img-x));
            }
            /*100% {translate: calc(-6 * var(--img-w));}*/
            /*100% {translate: calc(-7 * var(--img-w));}*/
        }

        .carousel ul li {
            display: inline-block;
        }

        .carousel ul li img {
            width: var(--img-w);
            height: var(--img-h);
            margin: 15px var(--img-m);
            border: 10px outset gold;
            box-sizing: border-box;
            box-shadow: 1px 1px 10px 5px dimgrey;
            object-fit: cover;
            object-position: center center;
        }

    </style>
</head>
<body>
    <div id="app">
        <div class="carousel">
            <ul>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
                <li><img src="" alt=""/></li>
            </ul>
        </div>
    </div>
</body>
<script>
    const srcString = "'https://img2.baidu.com/it/u=421347826,2792415000&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img2.baidu.com/it/u=3123880262,455523890&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=4139606063,194286789&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=130504489,1044576680&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img0.baidu.com/it/u=2696759067,1221490204&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img1.baidu.com/it/u=1423197334,186448263&fm=253&fmt=auto&app=138&f=JPEG?w=491&h=492', " +
        "'https://img2.baidu.com/it/u=2391751777,1392423538&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', " +
        "'https://img1.baidu.com/it/u=2241852295,652512022&fm=253&fmt=auto&app=138&f=JPEG?w=523&h=500'";
    const imgNodeList = document.querySelectorAll(".carousel ul li img");
    srcString.split(", ").forEach((src, index) => {
        console.log(src)
        imgNodeList[index].setAttribute("src", src.substring(1, src.length - 1));
    });
</script>
</html>