分割轮播——分久必合,合久必分
相信每一位前端开发者,徒手撸个轮播啊,选项卡啊,树形菜单啊应该没啥难度,那我们也来写一个吧?
这个轮播呢?稍微有点特殊,不像传统的一张图一张图的显示,而是把要显示的一张图先拆了,变成一个个的散块,再组装。
大概效果是这样的吧:传送门
想看完整代码的,请移步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这两个属性),这样我们就很简单的把图片拆开来了。(可以想想我为什么要这样做)
好了,核心的原理讲完了,那整个的流程逻辑具体是怎么实现的呢?我呢,这里提供一种思路,仅供参考:
① : 拆分图片,我这里呢取了个巧,页面的写法就是跟平时轮播一样,这时候你有疑惑了,用于装拆分后的那些图片碎片的容器(li,div啥的都行),哪去了?
② : 其实啊,上面html里写的这个,最终里面的ul是被我删掉的,我只不过去读取了这里面所有图片的src,仅此而已。
③ : 那你还是没回答我的疑惑,容器哪里来?我这里做了些小取巧,刚刚说的上面这个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?这个和$有区别没?你说一个是元素一个是对象,嗯是的,还有吗?留点时间,充实下自己的双脚,站在巨人肩膀上的同时,也要踏稳,防止上面的风大,将你吹入万丈深渊,好了,咱们呢,暂时就到这吧。
共同学习,写下你的评论
评论加载中...
作者其他优质文章