效果参考最终王冠的官网 https://zzwg.xd.com/
JS
1 ;window.requestAnimationFrame = window.requestAnimationFrame||function(a){return setTimeout(a,1000/60)}; 2 window.cancelAnimationFrame = window.cancelAnimationFrame||clearTimeout; 3 function FragmentBanner(option) { 4 5 //实例化时,可传的参数 6 this.whiteList = ['container','controller','size','imgs','size','grid','index','fnTime','boxTime','type']; 7 8 //容器将包容控制器 9 this.container = '.banner'; 10 11 //默认的控制器 12 this.controller = { 13 view : '.banner-view', 14 btn : '.banner-btn', 15 num : '.banner-number', 16 progre : '.banner-progres' 17 }; 18 19 //栅格 行*列 20 this.grid = { 21 line : 5, 22 list : 10 23 }; 24 25 //容器的大小 26 this.size = { 27 width : 1200, 28 height : 675, 29 }; 30 31 //切换类型 32 this.type = 1; 33 34 //索引位置 35 this.index = 0; 36 37 //函数每次切换时间 38 this.fnTime = 5000; 39 40 //栅格每次运动时间 41 this.boxTime = 2000; 42 43 //栅格运动结束的时间 44 this.activeTime = new Date(); 45 46 for(var a = 0,attrLenght = this.whiteList.length; a < attrLenght;a++){ 47 48 var attr = this.whiteList[a]; 49 if(option[attr] != undefined){ 50 51 this[attr] = option[attr]; 52 } 53 } 54 for(var i in option){ 55 56 if(this.whiteList[i] !== undefined){ ; } 57 } 58 59 this.init(); 60 } 61 62 FragmentBanner.prototype = { 63 64 constructor : FragmentBanner, 65 66 init : function(){ 67 68 this.container = document.querySelector(this.container) 69 if(!this.container){ 70 71 return alert('获取banner容器失败'); 72 }else{ 73 74 this.container.style.width = this.size.width+'px'; 75 this.container.style.height = this.size.height+'px'; 76 } 77 78 this.elem = {}; 79 for(var e in this.controller){ 80 81 this.elem[e] = this.container.querySelector(this.controller[e]); 82 if(this.elem[e] == null){ 83 84 return alert('获取'+e+'容器'); 85 } 86 } 87 88 //栅格 89 var w = this.size.width / this.grid.list, 90 h = this.size.height / this.grid.line; 91 92 this.elem.viewBox = new Array(); 93 for(var i = 0,iL = this.grid.line;i < iL;i++){ 94 95 for(var j = 0,jL = this.grid.list;j < jL;j++){ 96 97 var newI = document.createElement('i'); 98 99 this.setCss(newI,{ 100 width : w+'px', 101 height : h+'px', 102 left : 0, 103 top : 0, 104 opacity : 1, 105 backgroundImage : 'url("'+this.imgs[this.index]+'")', 106 backgroundSize : this.size.width + 'px ' + this.size.height +'px', 107 backgroundPosition : w * -j+'px ' + h * -i+'px' 108 }); 109 110 this.elem.view.appendChild(newI); 111 this.elem.viewBox.push(newI); 112 } 113 } 114 115 //按钮动作 116 for (var b = 1; b >= 0; b--) { 117 118 var oB = document.createElement('span'); 119 (b) ? oB.innerHTML = '<' : oB.innerHTML = '>'; 120 oB.setIndex = b; 121 oB.onclick = function(obj){ 122 123 this.show({ 124 switch : true, 125 change : obj.setIndex == 0 126 }); 127 128 }.bind(this,oB); 129 this.elem.btn.appendChild(oB); 130 } 131 132 //数量 133 for(var n = 0,nL = this.imgs.length; n < nL;n++){ 134 135 var oI = document.createElement('i'); 136 137 oI.setIndex = n; 138 oI.onclick = function(obj){ 139 140 //显示动画 141 this.show({ 142 switch : true, 143 change : obj.setIndex 144 }); 145 }.bind(this,oI) 146 this.elem.num.appendChild(oI); 147 } 148 this.elem.numFind = this.elem.num.querySelectorAll('i'); 149 150 //进度条 151 this.progre = new Array; 152 for(var p = 1;p >= 0;p--){ 153 154 var oP = document.createElement('i'); 155 this.setCss(oP,{ 156 width : 0, 157 backgroundColor : p ? '#00c3ff' : '#ffc300' 158 }); 159 this.elem.progre.appendChild(oP); 160 this.progre.push(oP); 161 } 162 163 //显示动画 164 this.show(); 165 166 this.elem.numFind[this.index].className = 'on'; 167 }, 168 169 setIndex : function(){ 170 171 this.index %= this.imgs.length; 172 173 this.index = (this.index < 0) ? this.imgs.length - 1 : this.index; 174 175 this.elem.numFind[this.index].className = 'on'; 176 }, 177 178 getTypeTime : function(){ 179 180 var timer = new Array(); 181 switch(this.type){ 182 183 case 1: 184 185 timer.push(this.boxTime / 4 + Math.random() * this.boxTime / 4); 186 timer.push(timer[0]); 187 break; 188 189 default: 190 191 timer.push([Math.random() * this.boxTime / 5,this.boxTime / 10 * 3]); 192 timer.push(timer[0][0] + timer[0][1]); 193 break; 194 } 195 196 return timer; 197 }, 198 199 show : function(order){ 200 201 order = order || {}; 202 203 if(new Date() >= this.activeTime){ 204 205 this.elem.numFind[this.index].className = ''; 206 207 //下次播放动画时候的进度条 208 this.setCss(this.progre[1],{width : 0}) 209 .anime(this.progre[1],{ 210 width : this.size.width 211 },this.fnTime,function(){ 212 213 this.show({ 214 switch : true, 215 change : true 216 }); 217 }.bind(this)); 218 219 var status = true, 220 activeTime = 0; 221 222 for( var i = 0,iL = this.elem.viewBox.length;i < iL;i++ ){ 223 224 var startTime = this.getTypeTime(), 225 endTime = this.getTypeTime(), 226 obj = this.elem.viewBox[i]; 227 228 activeTime = Math.max(activeTime,startTime[1] + endTime[1]); 229 230 this.anime(obj,{ 231 left : Math.ceil(Math.random() * this.size.width * 2 - this.size.width), 232 top : Math.ceil(Math.random() * this.size.height * 2 - this.size.height), 233 opacity: 0 234 }, startTime[0] ,function(obj){ 235 236 if(order.switch && status){ 237 238 if(/number/i.test(typeof order.change)){ 239 240 this.index = order.change; 241 }else{ 242 243 (order.change) ? ++this.index : --this.index; 244 } 245 246 this.setIndex(); 247 this.elem.numFind[this.index].className = 'on'; 248 status = false; 249 } 250 251 this.setCss(obj,{backgroundImage : 'url("'+this.imgs[this.index]+'")'}) 252 .anime(obj,{ 253 left : 0, 254 top : 0, 255 opacity : 1 256 },endTime[0]); 257 }.bind(this,obj)); 258 } 259 260 //栅格结束运动的时间 261 this.activeTime = new Date(new Date().getTime() + activeTime); 262 263 this.setCss(this.progre[0],{width : 0}) 264 .anime(this.progre[0],{ 265 width : this.size.width 266 },activeTime); 267 } 268 }, 269 270 setCss : function(obj,json){ 271 272 for( c in json){ 273 274 if(c == 'opacity'){ 275 276 obj.style.opacity = c; 277 obj.style.filter = "alpha(opacity="+ (json[c]*100) +")"; 278 }else{ 279 280 obj.style[c] = json[c]; 281 } 282 } 283 284 return this; 285 }, 286 287 anime : function(obj,attr,endTime,callback) { 288 289 (obj.timer) && cancelAnimationFrame(obj.timer); 290 291 var cssJosn = obj.currentStyle || getComputedStyle(obj,null), 292 start = {},end = {},goTime; 293 294 //设置初始属性值和结束属性值 295 for(var key in attr){ 296 297 if(attr[key] != parseFloat(cssJosn[key])){ 298 299 start[key] = parseFloat(cssJosn[key]); 300 end[key] = attr[key] - start[key]; 301 } 302 } 303 304 goTime = new Date(); 305 306 if(endTime instanceof Array){ 307 308 (function delayFn(){ 309 310 if((new Date() - goTime) >= endTime[0]){ 311 312 endTime = endTime[1]; 313 goTime = new Date(); 314 ref(); 315 }else{ 316 317 obj.timer = requestAnimationFrame(delayFn); 318 } 319 })(); 320 }else{ 321 322 ref(); 323 } 324 325 326 function ref(){ 327 328 var prop = (new Date() - goTime) / endTime; 329 (prop >= 1) ? prop = 1 : obj.timer = requestAnimationFrame(ref); 330 for(var key in start){ 331 332 var val = -end[key] * prop *(prop-2) + start[key]; 333 334 if(key == 'opacity'){ 335 336 obj.style.opacity = val; 337 obj.style.filter = "alpha(opacity="+ (val*100) +")"; 338 }else{ 339 340 obj.style[key] = val+'px'; 341 } 342 } 343 344 (prop === 1) && callback && callback.call(obj); 345 }; 346 } 347 }
CSS
*{ margin: 0; padding: 0; } .banner{ position: relative; overflow: hidden; } .banner-view{ position: relative; height: 100%; z-index: 999; background-color: #090b22; background-repeat: no-repeat; } .banner-view i{ position: relative; display: block; float: left; background-repeat: no-repeat; } .banner-btn{ position: absolute; width: 100%; height: 0; top: 45%; font-family: "宋体"; font-size: 20px; z-index: 1000; } .banner-btn span{ display: block; float: left; width: 50px; line-height: 50px; text-align: center; background-color: rgba(0,0,0,0.7); color: #74dcff; cursor: pointer; font-weight: 800; background-image: } .banner-btn span:hover{ background-color: rgba(0,0,0,0.6); } .banner-btn span + span{ float: right; } .banner-number{ position: absolute; bottom: 35px; width: 100%; height: 0; font-size: 0; text-align: center; z-index: 1000; } .banner-number > *{ display: inline-block; border: 2px solid #fff; border-radius: 50%; margin: 0 8px; width: 10px; height: 10px; background-color: #00c3ff; cursor: pointer; } .banner-number > *:hover, .banner-number > *.on{ background-color: #ffc300; } .banner-progres{ width: 100%; position: absolute; bottom: 0; height: 3px; z-index: 1000; } .banner-progres i{ position: absolute; left: 0; top: 0; border-radius: 3px; display: block; height: 100%; width: 0; }
HTML
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <link rel="stylesheet" type="text/css" href="css/banner.css"> <title>banner图碎片化</title> </head> <body style="background-color:#F1F1F1"> <div class="banner" id="banner1" style="margin: 50px auto;"> <div class="banner-view"></div> <div class="banner-btn"></div> <div class="banner-number"></div> <div class="banner-progres"></div> </div> <script type="text/javascript" src="js/banner.js"></script> <script type="text/javascript"> var banner = new FragmentBanner({ container : "#banner1",//选择容器 必选 imgs : ['images/a1.png','images/a2.png','images/a3.png','images/a4.png','images/a5.png'],//图片集合 必选 size : { width : 1000, height : 560 },//容器的大小 可选 //行数与列数 可选 grid : { line : 12, list : 14 }, index: 0,//图片集合的索引位置 可选 type : 2,//切换类型 1 , 2 可选 boxTime : 5000,//小方块来回运动的时长 可选 fnTime : 10000//banner切换的时长 可选 }); </script> </body> </html>