写正文前先吐槽一下:端午放假完第一天去某千人以上公司面试前端工程师,第一轮是我应聘职位的部门小领导,谈的不错,面试主要围绕要用到的技术来;第二轮来了我要说的正主,我了个去,问的问题一个和前端无关,问我什么是“死锁”,实现二叉树的先序遍历的算法,我真的想知道我面试的是前端么,职责不是用React框架实现公司官网的维护和迭代么。我不否认他问的这些知识点属于某一领域内的基础,但是我哪个前端工程师非必要的情况下在工作2,3年内专门去了解这些工作中几乎用不到的知识呢。我前端都学不完,没学透呢。
昨天晚上看完欧冠决赛,今天一觉醒来已是下午,吃过饭就寻思着写点什么,正好上周花了好几个小时温习原型、原型对象、原型链的知识,这次就用原型的概念实现图片网格式效果(网上大多是利用jQuery实现,jQuery提供的很多额外的方法和选择器确实方便许多)。
先给出效果图:
写的小组件支持图片的渐显、渐隐,并且可以是有序、随机两种方式。
我采用的原型是属性写在构造函数内,方法写在原型对象内。方法写构造函数内有个问题,就是每次调用这个方法就相当于重新实例化一次,举个粟子:
实现网格效果的原理上是将读取图片的宽高,按照设定的参数,分成等高宽的网格(我用的span标签表示的网格),网格利用定位铺满整个图片,接下来就是按照设定的顺序实现渐显或渐隐。渐显或渐隐用的是JS的animation属性和CSS3的animation属性在属性值上有所区别,这次使用也才知道JS的animation属性里有个animationFillMode(规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。)属性值。
我绑定的事件是点击,完全可以用其他事件或页面加载触发。我的代码稍加改动就可以实现网格式轮播图。
下面给出源代码:
1 <!doctype html> 2 <head> 3 <title>网格效果</title> 4 <style> 5 @charset "utf-8"; 6 /*css reset*/ 7 html{font-family:"Helvetica Neue",Helvetica,STHeiTi,sans-serif;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;} 8 body{-webkit-overflow-scrolling:touch;margin:0;} 9 ul{margin:0;padding:0;list-style:none;outline:none;} 10 dl,dd{margin:0;} 11 a{display:inline-block;margin:0;padding:0;text-decoration:none;background:transparent;outline:none;color:#000;} 12 a:link,a:visited,a:hover,a:active{text-decoration:none;color:currentColor;} 13 a,dt,dd{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;} 14 img{border:0;} 15 p{margin:0;} 16 input,button,select,textarea{margin:0;padding:0;border:0;outline:0;background-color:transparent;} 17 /*css*/ 18 .origin-pic { 19 display: inline-block; 20 width: 200px; 21 height: 200px; 22 } 23 24 .grid-area { 25 display: inline-block; 26 position: relative; 27 width: 200px; 28 height: 200px; 29 } 30 31 .grid { 32 position: absolute; 33 } 34 35 #img1 { 36 opacity: 1; 37 width: 200px; 38 height: 200px; 39 } 40 41 @keyframes fadeout{ 42 0% {opacity: 1} 43 100% {opacity: 0} 44 } 45 46 @keyframes fadein{ 47 0% {opacity: 0} 48 100% {opacity: 1} 49 } 50 </style> 51 </head> 52 <body> 53 <div> 54 <img class="origin-pic" src="./pic.jpg" /> 55 </div> 56 <div id="grid_area" class="grid-area"> 57 <img id="img1" src="./pic.jpg" /> 58 </div> 59 60 <script> 61 var gridSetting = { 62 ‘cell‘: 10, // 行、列数量 63 ‘mode‘: ‘fadeout‘, // 备选参数: fadeout, fadein 64 ‘sort‘: ‘random‘, // 备选参数: inturn, random 65 ‘num‘: 1, // 每次发生动作的网格数,目前只支持1 66 complete: function() { // 事件完成时的回调函数 67 console.log(‘ok!‘); 68 } 69 }; 70 var img1 = document.getElementById(‘img1‘); 71 (function(doc, setting, ele) { 72 var defaults = { 73 ‘speed‘: 20, 74 }; 75 76 function Grid(ele) { 77 this.ele = ele; 78 this.settings = Object.assign({}, setting, defaults); 79 } 80 81 Grid.prototype = { 82 constructor: Grid, 83 84 // 构建UI 85 _create: function() { 86 var img = this.ele, 87 settings = this.settings, 88 cell = settings.cell, 89 imgWidth = img.width, 90 imgHeight = img.height, 91 gridWidth = imgWidth / cell, // 每个网格宽度 92 gridHeight = imgHeight / cell, // 每个网格高度 93 currentTop = 0, 94 currentLeft = 0, 95 fragment = doc.createDocumentFragment(), 96 i = 0, 97 gridArr = []; 98 img.style.display = ‘none‘; 99 for (; i < cell * cell; i++) { 100 var spanNode = doc.createElement(‘span‘); 101 spanNode.setAttribute(‘id‘, i); 102 spanNode.style.cssText += ‘position: absolute;‘ + 103 ‘top: ‘ + currentTop + ‘px;‘ + 104 ‘left: ‘ + currentLeft + ‘px;‘ + 105 ‘margin: 0;‘ + 106 ‘padding: 0;‘ + 107 ‘width: ‘ + gridWidth + ‘px;‘ + 108 ‘height: ‘ + gridHeight + ‘px;‘ + 109 ‘opacity:‘ + settings.opacity + ‘;‘ + 110 ‘background: url(‘+ img.src + ‘);‘ + 111 ‘background-size: ‘ + imgWidth + ‘px ‘ + imgHeight + ‘px;‘ + 112 ‘background-position: -‘ + currentLeft + ‘px -‘ + currentTop + ‘px;‘; 113 if (currentLeft < (imgWidth - gridWidth)) { 114 currentLeft += gridWidth; 115 } else { 116 currentLeft = 0; 117 currentTop += gridHeight; 118 } 119 fragment.append(spanNode); 120 gridArr.push(i); 121 } 122 this.gridArr = gridArr; 123 doc.getElementById(‘grid_area‘).append(fragment); 124 }, 125 126 // 渐显、渐隐 127 _fade: function() { 128 var gridArr = this.gridArr, 129 cloneArr = gridArr.slice(0), 130 length = gridArr.length, 131 settings = this.settings, 132 sort = settings.sort, 133 i = 0; 134 switch(settings.mode) { 135 case ‘fadeout‘: 136 if (sort == ‘inturn‘) { 137 // 按顺序渐隐 138 var timer = setInterval(function() { 139 doc.getElementById(gridArr[i]).style.animation = "fadeout 1s forwards"; 140 i++; 141 if (i >= settings.cell * settings.cell) { 142 clearInterval(timer); 143 settings.complete(); 144 } 145 }, settings.speed) 146 } else if (sort == ‘random‘) { 147 // 随机渐隐 148 var timer = setInterval(function() { 149 i = cloneArr.splice(Math.random() * length--, 1); 150 doc.getElementById(gridArr[i]).style.animation = "fadeout 1s forwards"; 151 if (length == 0) { 152 clearInterval(timer); 153 settings.complete(); 154 } 155 }, settings.speed) 156 } 157 break; 158 case ‘fadein‘: 159 if (sort == ‘inturn‘) { 160 // 按顺序渐渐显 161 var timer = setInterval(function() { 162 doc.getElementById(gridArr[i]).style.animation = "fadein 1s forwards"; 163 i++; 164 if (i >= settings.cell * settings.cell) { 165 clearInterval(timer); 166 settings.complete(); 167 } 168 }, settings.speed) 169 } else if (sort == ‘random‘) { 170 // 随机渐显 171 var timer = setInterval(function() { 172 i = cloneArr.splice(Math.random() * length--, 1); 173 doc.getElementById(gridArr[i]).style.animation = "fadein 1s forwards"; 174 if (length == 0) { 175 clearInterval(timer); 176 settings.complete(); 177 } 178 }, settings.speed) 179 } 180 break; 181 default: 182 console.log(‘配置错误!‘); 183 } 184 185 186 }, 187 188 _checkMode: function() { 189 if (this.settings.mode == ‘fadein‘) { 190 this.settings.opacity = 0; 191 } else { 192 this.settings.opacity = 1; 193 } 194 }, 195 196 }; 197 198 var gridArea = doc.getElementById(‘grid_area‘); 199 gridArea.addEventListener(‘click‘, function() { 200 var event = new Grid(ele); 201 event._checkMode(); 202 event._create(); 203 event._fade(); 204 }, false); 205 })(document, gridSetting, img1); 206 </script> 207 </body> 208 </html>