zoukankan      html  css  js  c++  java
  • 原生js实现图片网格式渐显、渐隐效果

      昨天晚上看完欧冠决赛,今天一觉醒来已是下午,吃过饭就寻思着写点什么,正好上周花了好几个小时温习原型、原型对象、原型链的知识,这次就用原型的概念实现图片网格式效果(网上大多是利用jQuery实现,jQuery提供的很多额外的方法和选择器确实方便许多)。

      先给出效果图:

      

      写的小组件支持图片的渐显、渐隐,并且可以是有序、随机两种方式。

      我采用的原型是属性写在构造函数内,方法写在原型对象内。方法写构造函数内有个问题,就是每次调用这个方法就相当于重新实例化一次,举个粟子:

      

      实现网格效果的原理上是将读取图片的宽高,按照设定的参数,分成等高宽的网格(我用的span标签表示的网格),网格利用定位铺满整个图片,每个网格的背景图都是原图片,原理同sprite,利用background-position属性改变显示区域。接下来就是按照设定的顺序实现渐显或渐隐。渐显或渐隐用的是JS的animation属性和CSS3的animation属性在属性值上有所区别,这次使用也才知道JS的animation属性里有个animationFillMode(规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。)属性值

      我绑定的事件是点击,完全可以用其他事件或页面加载触发。

      毫无疑问渐隐、渐显效果实现部分的代码很有问题,从重构的角度来说,代码内容出现重复就可以提炼出一个新函数。说实话js的原型、原型链的基础知识掌握的比较全,但是在工作中几乎没用到过,可能用的多就就是给引用类型Array扩展一个indexOf()方法等,用原型的概念编写小应用还真是第一次,我也会去下载一些相关插件,看看它们的源码中是如何用原型的概念来编程的。

      下面给出源代码:

      

      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                                             ' ' + 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.appendChild(spanNode);
    120                 gridArr.push(i);
    121             }
    122             this.gridArr = gridArr;
    123             doc.getElementById('grid_area').appendChild(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>

      2017年6月21日补充:

        关于构造函数在立即执行函数体外的实例化方式:

     1     (function() {
     2         function Person1() {
     3             this.say = function() {
     4                 console.log(1)
     5             }
     6         }
     7 
     8         var Person2 = function() {
     9             this.say = function() {
    10                 console.log(2)
    11             }
    12         }
    13 
    14         Person3 = function() {
    15             this.say = function() {
    16                 console.log(3)
    17             }
    18         }
    19 
    20         var Person4 = function() {
    21             this.say = function() {
    22                 console.log(4)
    23             }
    24         }
    25 
    26         function Person5() {
    27             this.say = function() {
    28                 console.log(5)
    29             }
    30         }
    31 
    32         window.Person4 = Person4;
    33         window.Person5 = Person5;
    34     })()
    35     // Person1 is not defined
    36     // var person1 = new Person1();
    37     // person1.say();
    38 
    39     // Person2 is not defined
    40     // var person2 = new Person2();
    41     // person2.say();
    42 
    43     // 3
    44     var person3 = new Person3();
    45     person3.say();
    46 
    47 
    48     // 4
    49     var person4 = new Person4();
    50     person4.say();
    51 
    52     // 5
    53     var person5 = new Person5();
    54     person5.say();
  • 相关阅读:
    ArrayList源码剖析
    Qt线程外使用Sleep
    malloc、calloc和realloc比较
    C++各大名库
    Qt 编译boost
    VC++ 设置控件显示文本的前景色、背景色以及字体
    std::map的操作:插入、修改、删除和遍历
    time.h文件中包含的几个函数使用时须注意事项
    赋值操作符和拷贝构造函数
    virtual析构函数的作用
  • 原文地址:https://www.cnblogs.com/youyouluo/p/6942039.html
Copyright © 2011-2022 走看看