为了账号安全,请及时绑定邮箱和手机立即绑定

分割轮播——分久必合,合久必分

        相信每一位前端开发者,徒手撸个轮播啊,选项卡啊,树形菜单啊应该没啥难度,那我们也来写一个吧?

        这个轮播呢?稍微有点特殊,不像传统的一张图一张图的显示,而是把要显示的一张图先拆了,变成一个个的散块,再组装。

        大概效果是这样的吧:传送门

        想看完整代码的,请移步github:github地址

        那这样的效果是怎么做出来的呢?

        先看看html吧,你会发现跟我们平时写一个轮播没有啥区别,那它到底是怎么实现拆分的呢?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>切个轮播</title>
 <!--<link rel="stylesheet" href="../../dist/common.css" type="text/css">-->
 <link rel="stylesheet" href="cutting-carousel.css" type="text/css">
 <!--
        @author : dorseyCh
        @date : 2018-09-06  11:25
        @mine : I am a boy with a dream, who want to make some achievements in software industry,little but clinging.
    -->
</head>
<body>

    <div class = "dc-carousel">
        <ul class = "carousel-data">
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/1.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/2.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/3.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/4.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/5.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/6.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/7.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/8.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/9.jpg"></li>
            <li><img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/10.jpg"></li>
        </ul>
    </div>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../../dist/jquery-3.3.1.min.js" type="text/javascript"></script>
    <script src = "cutting-caroused.js" type="text/javascript"></script>

    <script>
 var carousel = new Carousel({
 pieces : 10 //表示要把整体切成几块,这里传一个数,它就会自动把图片切成多少块
 });
 carousel.circulation();
 </script>
</body>
</html>

        还记得我们在给div啥的设置背景图片的时候,对于背景图片是怎么定义的呢?啊,我想到了,no-repeat,嗯,这个是啥?有什么作用,除此之外你还想到什么?background-size?又有什么作用呢?background-position?这个呢?

        如果我们要给div设置背景色,最常见的做法就是把这个div铺满,但是你有没有遇到一个问题?比如我们有时候设置背景图的时候图片太大div只显示了一部分,或者太小没占满?还有比较特殊的要求,只显示从哪个位置到哪个位置的图片区域。那对于这些我们怎么做呢?

其实实现它的核心原理很简单:

        其实每张图我们可以通过定位的方式来让其只显示其中一部分,就像一幅很大的山水画,上面盖了一层白布(蒙版),那我们的一个个的li啊,div啊就是白布的破洞,或者说开出的小窗,我们是不是就看到下面的图片了?而定位也是一样的,通过把每个li设定一个背景,这个背景是这张要显示的图片的一部分(不太懂的呢,可以细细去了解下background-size,background-position这两个属性),这样我们就很简单的把图片拆开来了。(可以想想我为什么要这样做)

https://img1.sycdn.imooc.com//5b91406f00017b4007620186.jpg

        好了,核心的原理讲完了,那整个的流程逻辑具体是怎么实现的呢?我呢,这里提供一种思路,仅供参考:

         ① : 拆分图片,我这里呢取了个巧,页面的写法就是跟平时轮播一样,这时候你有疑惑了,用于装拆分后的那些图片碎片的容器(li,div啥的都行),哪去了?

         ② : 其实啊,上面html里写的这个,最终里面的ul是被我删掉的,我只不过去读取了这里面所有图片的src,仅此而已。

https://img1.sycdn.imooc.com//5b91414500017b8807040436.jpg

        ③ : 那你还是没回答我的疑惑,容器哪里来?我这里做了些小取巧,刚刚说的上面这个div里的ul被我删了,删之前呢,我读取了这些图片的数据,再读取了用户传进来的参数,就是要拆成几个?对吧?那再重新创建一个ul不就好了?这个ul就不管原来有多少张照片了,只管你要拆成几个?有几个我就创建几个li,这样把新的ul插回到页面里的时候呢,实际上只显示了一张图片。注意,这里只有一张图,每个li显示的是拆分后的图的各个部分。

        ④ : 说到这应该就很简单了吧?无非就是每一轮换新的图片呢,把li的背景图片的路径给改了,改成啥呢?就是我们前面读取的各个图片的路径发光发热了。这样再配合一些css3小动画,整体就很炫酷了。呵呵。

        好了,不说了,一起看看代码吧(html部分上面已经有了咱们就不再啰嗦,jQuery请自行百度):

        css

/*
 *  动画相关
 *  这里引用了animate.css中的部分动画,大家可以百度搜索animate.css,体会体会CSS3给我们带来的强大动画效果。
 *  有时间有能力建议深入去学习下canvas,D3.js等,对现在的大数据趋势会有很大帮助(数据可视化)
**/
@-webkit-keyframes bounceInRight {
    from,
    60%,
    75%,
    90%,
    to {
      -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
      animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    }
  
    from {
      opacity: 0;
      -webkit-transform: translate3d(3000px, 0, 0);
      transform: translate3d(3000px, 0, 0);
    }
  
    60% {
      opacity: 1;
      -webkit-transform: translate3d(-25px, 0, 0);
      transform: translate3d(-25px, 0, 0);
    }
  
    75% {
      -webkit-transform: translate3d(10px, 0, 0);
      transform: translate3d(10px, 0, 0);
    }
  
    90% {
      -webkit-transform: translate3d(-5px, 0, 0);
      transform: translate3d(-5px, 0, 0);
    }
  
    to {
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0);
    }
  }
  
  @keyframes bounceInRight {
    from,
    60%,
    75%,
    90%,
    to {
      -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
      animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    }
  
    from {
      opacity: 0;
      -webkit-transform: translate3d(3000px, 0, 0);
      transform: translate3d(3000px, 0, 0);
    }
  
    60% {
      opacity: 1;
      -webkit-transform: translate3d(-25px, 0, 0);
      transform: translate3d(-25px, 0, 0);
    }
  
    75% {
      -webkit-transform: translate3d(10px, 0, 0);
      transform: translate3d(10px, 0, 0);
    }
  
    90% {
      -webkit-transform: translate3d(-5px, 0, 0);
      transform: translate3d(-5px, 0, 0);
    }
  
    to {
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0);
    }
  }
  
  .bounceInRight {
    -webkit-animation-name: bounceInRight;
    animation-name: bounceInRight;
  }


  @-webkit-keyframes bounceOutLeft {
    20% {
      opacity: 1;
      -webkit-transform: translate3d(20px, 0, 0);
      transform: translate3d(20px, 0, 0);
    }
  
    to {
      opacity: 0;
      -webkit-transform: translate3d(-2000px, 0, 0);
      transform: translate3d(-2000px, 0, 0);
    }
  }
  
  @keyframes bounceOutLeft {
    20% {
      opacity: 1;
      -webkit-transform: translate3d(20px, 0, 0);
      transform: translate3d(20px, 0, 0);
    }
  
    to {
      opacity: 0;
      -webkit-transform: translate3d(-2000px, 0, 0);
      transform: translate3d(-2000px, 0, 0);
    }
  }
  
  .bounceOutLeft {
    -webkit-animation-name: bounceOutLeft;
    animation-name: bounceOutLeft;
  }

  .animated {
    -webkit-animation-duration: 1s;
    animation-duration: 1s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
  }

  /*common.css*/
  html,body,div,ul,li,input,p,h1,h2,h3,h4,h5,h6,dd,dt,dl,tr,td,th{
    margin : 0;
    padding : 0;
  }
  ul,li {
    list-style: none;
  }

  /*样式*/
  body{overflow:hidden}
  .carouselDisplay{width:100%;height:100%;}
  .carouselDisplay li{
    height : 100%;
    float : left;
  }
  .carouselDisplay img{
    width:100%;
    height:100%;
  }
  .carousel-data{
    display : none;
  }

.dc-carousel{
  width:100%;
  height:100%;
}

        js

(function(win){
    "use strict";
    var Carousel = function (option) {
        this.option = option;
    };
    /*整个分割轮播的核心————一张图片可以通过不同的定位方式获取到图片里不同位置的图画,一个img可以通过设立比如10个li,或者10个div的背景图分别为改图片的一部分,
    这样就实现了图片的分割,再辅以动画,就可以实现分割轮播*/
    Carousel.prototype = {
        
        //初始化作为中转站的dom
        init : function () {
            
            var _self = this;
            
            var height = document.documentElement.clientHeight;
                // width = document.documentElement.clientWidth;

            /*
                函数传入的参数处理
            */
            _self.number =  _self.option.pieces ? _self.option.pieces : 5;  //函数传入的参数,这里是要切成几块,没传参数默认切成0块

            _self.index = 0;

            // 这个注释的唯一作用仅仅是便于理解整个的思路,即把整张图片切成几块,看到下面的li_node += "<li></li>"吗?
            // 也许你看了我注释的这个_self.dom就会明白我为什么要这样做了。

            // _self.dom = `<ul class = "carouselDisplay dc-doc-height">
            //                 <li></li>
            //                 <li></li>
            //                 <li></li>
            //                 <li></li>
            //                 <li></li>
            //             </ul>`;

            _self.image = [];   //接收上方的img中的src并转化成url(src)
            
            var li_node = "";   //用于切块的li
            
            $(".carousel-data").children("li").each(function(i){
                _self.image.push("url(" + $(this).children("img").attr("src") + ")");
            });

            /*看到上面的几块了吗,根据传入的参数增加单元个数*/
            for(var i = 0 ; i < _self.number ; i ++){
                li_node += "<li></li>"
            }

            _self.dom = "<ul class = 'carouselDisplay dc-doc-height'>" + li_node + "</ul>";

            $(".dc-carousel").html("");
            $(".dc-carousel").append($(_self.dom));
            $(".dc-doc-height").css("height", height + "px");
        },

        /*添加分割轮播动画*/
        addAnimate : function () {

            var _self = this;
            var $li = $(".carouselDisplay li");
            
            _self.index %= _self.image.length;

            $li.css("width", 100/_self.number + "%");
            $li.css("background" , _self.image[_self.index ++ ] + " no-repeat");
            $li.css("background-size",$("ul").width() + "px " + $("ul").height() + "px");

            /*根据使用者自定义分成n块*/
            $li.each(function(i){
                $(this).css("background-position" , i * 100 / (_self.number-1) + "%" + "0%");
            });
            
            $li.attr("class","animated bounceInRight");
            $li.each(function(i){
                $li.eq(i).css("animation-delay" , i / 10 + "s");
            });
            setTimeout(function() {
                $li.attr("class","animated bounceOutLeft");
                $li.each(function(i){
                    $li.eq(i).css("animation-delay" , i / 10 + "s");
                });
            },4000);
        },
        /*轮播*/
        circulation : function () {
            var _self = this;
            _self.init();
            _self.addAnimate();
            setInterval(function(){
                _self.addAnimate();
            },4300 + _self.number * 160);
        }
    }
    win.Carousel = Carousel;
})(window);

        总结,其实呢,现在直接操作dom的方式以后会越来越少,前端呢,现在也工程化有一段时间了,也渐渐的成熟,jQuery呢,很多人说快过时了,是,是有点,但是呢,不妨碍我们去学习它,再与原生的js(你想用ES6,ES7都行)互相印证,你会发现很多时候,为什么vue要这样子写?为什么html5里面多了很多新的特性,比如document.querySelector?这个和$有区别没?你说一个是元素一个是对象,嗯是的,还有吗?留点时间,充实下自己的双脚,站在巨人肩膀上的同时,也要踏稳,防止上面的风大,将你吹入万丈深渊,好了,咱们呢,暂时就到这吧。





点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消