相信每一位前端开发者,徒手撸个轮播啊,选项卡啊,树形菜单啊应该没啥难度,那我们也来写一个吧?
这个轮播呢?稍微有点特殊,不像传统的一张图一张图的显示,而是把要显示的一张图先拆了,变成一个个的散块,再组装。
大概效果是这样的吧:传送门
想看完整代码的,请移步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 src="img/1.jpg"></li>
<li><img src="img/2.jpg"></li>
<li><img src="img/3.jpg"></li>
<li><img src="img/4.jpg"></li>
<li><img src="img/5.jpg"></li>
<li><img src="img/6.jpg"></li>
<li><img src="img/7.jpg"></li>
<li><img src="img/8.jpg"></li>
<li><img src="img/9.jpg"></li>
<li><img src="img/10.jpg"></li>
</ul>
</div>
<script src="../../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?这个和$有区别没?你说一个是元素一个是对象,嗯是的,还有吗?留点时间,充实下自己的双脚,站在巨人肩膀上的同时,也要踏稳,防止上面的风大,将你吹入万丈深渊,好了,咱们呢,暂时就到这吧。


随时随地看视频