isotope神奇的动态布局库

HTML5应用开发:神奇的动态布局库isotope教程

1. isotope介绍

Isotope 是一个jQuery的插件,用来实现精美的动态元素布局。可以到http://isotope.metafizzy.co/demos/elements-complete.html了解一下大概情况。

Isotope可以实现仅仅依靠CSS3无法实现的动态布局方式,可以动态添加,删除,排序,筛选元素。Isotope的动画引擎可以充分使用现代浏览器CSS动画中GPU硬件加速性能,。

实例我已经上传到CSDN资源中,敬请下载。

2. 简单的isotope例子

Isotope要求jQuery1.4.3版本以上。首先需要在HTML页面中加载jQuery和isotope。

  1. <script src="../js/jquery-1.7.1.min.js"></script>  
  2. <script src="../jquery.isotope.min.js"></script>  

Isotope可以工作在一个包含很多类似item的container中,如下面所示:在div container中,声明了很累类似的div item。.

  1. <div id="container">  
  2.   <div class="item">…</div>  
  3.   <div class="item">…</div>  
  4.   <div class="item">…</div>  
  5.   …  
  6. </div>  

在JavaScript中,添加如下代码:

  1. $('#container').isotope({  
  2.   // options  
  3.   itemSelector : '.item',  
  4.   layoutMode : 'fitRows'  
  5. });  

itemSelector 用来指定container中用来动态排版的元素。

运行效果如下图所示:

调整窗口大小后,排列效果图。

 

3. Sorting and Filtering

在isotope中,可以动态地对元素进行排序和筛选。

排序的方式很多样化,可以按照元素的不同属性进行排序。首先在HTML页面中添加相应的option:

  1. <section id="options" class="clearfix">  
  2.     <h3>Sort</h3>  
  3.      <ul id="sort-by" class="option-set clearfix" data-option-key="sortBy">  
  4.       <li><a href="#sortBy=original-order" data-option-value="original-order" class="selected" data>original-order</a></li>  
  5.       <li><a href="#sortBy=name" data-option-value="name">name</a></li>  
  6.       <li><a href="#sortBy=symbol" data-option-value="symbol">symbol</a></li>  
  7.       <li><a href="#sortBy=number" data-option-value="number">number</a></li>  
  8.       <li><a href="#sortBy=weight"  data-option-value="weight">weight</a></li>  
  9.       <li><a href="#sortBy=category" data-option-value="category">category</a></li>  
  10.       <li><a href="#sortBy=random" data-option-value="random">random</a></li>  
  11.     </ul>  
  12.     <h3>Sort direction</h3>  
  13.     <ul id="sort-direction" class="option-set clearfix" data-option-key="sortAscending">  
  14.       <li><a href="#sortAscending=true" data-option-value="true" class="selected">sort ascending</a></li>  
  15.       <li><a href="#sortAscending=false" data-option-value="false">sort descending</a></li>  
  16.     </ul>  
  17.   </section> <!– #options –>  

我们看到,排序的方式包含了element所有的属性。可以进行升序排列也可以降序排列。

Element代码:

  1. <div class="element transition metal   " data-symbol="Hg" data-category="transition">  
  2.   <p class="number">80</p>  
  3.   <h3 class="symbol">Hg</h3>  
  4.   <h2 class="name">Mercury</h2>  
  5.   <p class="weight">200.59</p>  
  6. </div>  

在JavaScript中,对每个sorting的方法进行实现:

  1. $(function(){  
  2.   var $container = $('#container');  
  3.   $container.isotope({  
  4.     itemSelector : '.element',  
  5.     getSortData : {  
  6.       symbol : function( $elem ) {  
  7.         return $elem.attr('data-symbol');  
  8.       },  
  9.       category : function( $elem ) {  
  10.         return $elem.attr('data-category');  
  11.       },  
  12.       number : function( $elem ) {  
  13.         return parseInt( $elem.find('.number').text(), 10 );  
  14.       },  
  15.       weight : function( $elem ) {  
  16.         return parseFloat( $elem.find('.weight').text().replace( /[]/g, '') );  
  17.       },  
  18.       name : function ( $elem ) {  
  19.         return $elem.find('.name').text();  
  20.       }  
  21.     }  
  22.   });  
  23.     
  24.   var $optionSets = $('#options .option-set'),  
  25.       $optionLinks = $optionSets.find('a');  
  26.   $optionLinks.click(function(){  
  27.     var $this = $(this);  
  28.     // don't proceed if already selected  
  29.     if ( $this.hasClass('selected') ) {  
  30.       return false;  
  31.     }  
  32.     var $optionSet = $this.parents('.option-set');  
  33.     $optionSet.find('.selected').removeClass('selected');  
  34.     $this.addClass('selected');  
  35.   
  36.     // make option object dynamically, i.e. { filter: '.my-filter-class' }  
  37.     var options = {},  
  38.         key = $optionSet.attr('data-option-key'),  
  39.         value = $this.attr('data-option-value');  
  40.     // parse 'false' as false boolean  
  41.     value = value === 'false' ? false : value;  
  42.     options[ key ] = value;  
  43.     if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {  
  44.       // changes in layout modes need extra logic  
  45.       changeLayoutMode( $this, options )  
  46.     } else {  
  47.       // otherwise, apply new options  
  48.       $container.isotope( options );  
  49.     }  
  50.       
  51.     return false;  
  52.   });  
  53. });  

筛选的实现:isotope可以筛选不同属性的元素,需要对每个element属性通过class进行标记,如一个典型的element定义如下:

  1. <div class="element transition metal   " data-symbol="Hg" data-category="transition">  
  2.       <p class="number">80</p>  
  3.       <h3 class="symbol">Hg</h3>  
  4.       <h2 class="name">Mercury</h2>  
  5.       <p class="weight">200.59</p>  
  6.     </div>  

在class中表明该元素是transition 而且是metal和
sorting类似,在HTML中添加筛选的option:

  1. <section id="options" class="clearfix">  
  2.      
  3.      
  4.      <h3>Filters</h3>  
  5.   
  6.      <ul id="filters" class="option-set clearfix" data-option-key="filter">  
  7.        <li><a href="#filter" data-option-value="*" class="selected">show all</a></li>  
  8.        <li><a href="#filter" data-option-value=".metal">metal</a></li>  
  9.        <li><a href="#filter" data-option-value=".transition">transition</a></li>  
  10.        <li><a href="#filter" data-option-value=".post-transition">post-transition</a></li>  
  11.        <li><a href="#filter" data-option-value=".nonmetal">nonmetal</a></li>  
  12.        <li><a href="#filter" data-option-value=".inner-transition">inner-transition</a></li>  
  13.        <li><a href="#filter" data-option-value=".alkali, .alkaline-earth">alkali and alkaline-earth</a></li>  
  14.        <li><a href="#filter" data-option-value=":not(.transition)">not transition</a></li>  
  15.        <li><a href="#filter" data-option-value=".metal:not(.transition)">metal but not transition</a></li>  
  16.      </ul>  
  17.  </section> <!– #options –>  

对应的JavaScript function实现如下:

  1. $(function(){  
  2.         
  3.       var $container = $('#container');  
  4.   
  5.       $container.isotope({  
  6.         itemSelector : '.element'  
  7.       });  
  8.         
  9.         
  10.       var $optionSets = $('#options .option-set'),  
  11.           $optionLinks = $optionSets.find('a');  
  12.   
  13.       $optionLinks.click(function(){  
  14.         var $this = $(this);  
  15.         // don't proceed if already selected  
  16.         if ( $this.hasClass('selected') ) {  
  17.           return false;  
  18.         }  
  19.         var $optionSet = $this.parents('.option-set');  
  20.         $optionSet.find('.selected').removeClass('selected');  
  21.         $this.addClass('selected');  
  22.     
  23.         // make option object dynamically, i.e. { filter: '.my-filter-class' }  
  24.         var options = {},  
  25.             key = $optionSet.attr('data-option-key'),  
  26.             value = $this.attr('data-option-value');  
  27.         // parse 'false' as false boolean  
  28.         value = value === 'false' ? false : value;  
  29.         options[ key ] = value;  
  30.         if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {  
  31.           // changes in layout modes need extra logic  
  32.           changeLayoutMode( $this, options )  
  33.         } else {  
  34.           // otherwise, apply new options  
  35.           $container.isotope( options );  
  36.         }  
  37.           
  38.         return false;  
  39.       });  
  40.   
  41.         
  42.     });  

Filter demo演示,全部显示:

筛选所有metal的元素:

 

4. 动态添加元素

在isotope中,可以对container中的元素进行动态的删除和添加。

首先还是在HTML页面中添加相应的操作option:

  1. <section id="options">  
  2.    <ul class="clearfix">  
  3.      <li id="insert"><a href="#insert">Insert new elements</a></li>  
  4.      <li id="append"><a href='#append'>Append new elements</a></li>  
  5.      <li id="prepend"><a href='#prepend'>Prepend</a></li>  
  6.    </ul>  
  7.  </section>  

在对应的JavaScript中,添加对function的实现:

   
  1. $(function(){  
  2.     
  3.   var $container = $('#container');  
  4.   
  5.     
  6.   $('#insert a').click(function(){  
  7.     var $newEls = $( fakeElement.getGroup() );  
  8.     $container.isotope( 'insert', $newEls );  
  9.   
  10.     return false;  
  11.   });  
  12.   
  13.   $('#append a').click(function(){  
  14.     var $newEls = $( fakeElement.getGroup() );  
  15.     $container.append( $newEls ).isotope( 'appended', $newEls );  
  16.   
  17.     return false;  
  18.   });  
  19.   
  20.   
  21.   $('#prepend a').click(function(){  
  22.     var $newEls = $( fakeElement.getGroup() );  
  23.     $container  
  24.       .prepend( $newEls ).isotope('reloadItems').isotope({ sortBy: 'original-order' })  
  25.       // set sort back to symbol for inserting  
  26.       .isotope('option', { sortBy: 'symbol' });  
  27.   
  28.     return false;  
  29.   });  
  30.   
  31.   $container.isotope({  
  32.     itemSelector : '.element',  
  33.     filter: '*',  
  34.     getSortData : {  
  35.       symbol : function( $elem ) {  
  36.         return $elem.attr('data-symbol');  
  37.       }  
  38.     },  
  39.     sortBy : 'symbol'  
  40.   });  
  41.   
  42. });  
   

5. 不同的布局机制

在本例中,我们来尝试isotope中非常神奇的布局机制。

首先在HTML页面中,添加布局机制的选项:

  1. <section id="options" class="clearfix">  
  2.     
  3.   <h3>Layout modes</h3>  
  4.   
  5.   <ul id="layouts" class="option-set clearfix" data-option-key="layoutMode">  
  6.     <li><a href="#masonry" data-option-value="masonry" class="selected">masonry</a></li>  
  7.     <li><a href="#fitRows" data-option-value="fitRows">fitRows</a></li>  
  8.     <li><a href="#cellsByRow" data-option-value="cellsByRow">cellsByRow</a></li>  
  9.     <li><a href="#straightDown" data-option-value="straightDown">straightDown</a></li>  
  10.     <li><a href="#masonryHorizontal" data-option-value="masonryHorizontal" class="horizontal">masonryHorizontal</a></li>  
  11.     <li><a href="#fitColumns" data-option-value="fitColumns" class="horizontal">fitColumns</a></li>  
  12.     <li><a href="#cellsByColumn" data-option-value="cellsByColumn" class="horizontal">cellsByColumn</a></li>  
  13.     <li><a href="#straightAcross" data-option-value="straightAcross" class="horizontal">straightAcross</a></li>  
  14.   </ul>  
  15. </section> <!-- #options -->  

在JavaScript代码中实现相应的布局机制:

  
  1. $(function(){  
  2.     
  3.   var $container = $('#container');  
  4.     
  5.     
  6.   // add randomish size classes  
  7.   $container.find('.element').each(function(){  
  8.     var $this = $(this),  
  9.         number = parseInt( $this.find('.number').text(), 10 );  
  10.     if ( number % 7 % 2 === 1 ) {  
  11.       $this.addClass('width2');  
  12.     }  
  13.     if ( number % 3 === 0 ) {  
  14.       $this.addClass('height2');  
  15.     }  
  16.   });  
  17.     
  18.   $container.isotope({  
  19.     itemSelector : '.element',  
  20.     masonry : {  
  21.       columnWidth : 120  
  22.     },  
  23.     masonryHorizontal : {  
  24.       rowHeight: 120  
  25.     },  
  26.     cellsByRow : {  
  27.       columnWidth : 240,  
  28.       rowHeight : 240  
  29.     },  
  30.     cellsByColumn : {  
  31.       columnWidth : 240,  
  32.       rowHeight : 240  
  33.     }  
  34.   });  
  35.     
  36.     
  37.   // change layout  
  38.   var isHorizontal = false;  
  39.   function changeLayoutMode( $link, options ) {  
  40.     var wasHorizontal = isHorizontal;  
  41.     isHorizontal = $link.hasClass('horizontal');  
  42.   
  43.     if ( wasHorizontal !== isHorizontal ) {  
  44.       // orientation change  
  45.       // need to do some clean up for transitions and sizes  
  46.       var style = isHorizontal ?   
  47.         { height: '80%', width: $container.width() } :   
  48.         { width: 'auto' };  
  49.       // stop any animation on container height / width  
  50.       $container.filter(':animated').stop();  
  51.       // disable transition, apply revised style  
  52.       $container.addClass('no-transition').css( style );  
  53.       setTimeout(function(){  
  54.         $container.removeClass('no-transition').isotope( options );  
  55.       }, 100 )  
  56.     } else {  
  57.       $container.isotope( options );  
  58.     }  
  59.   }  
  60.   
  61.   
  62.     
  63.   var $optionSets = $('#options .option-set'),  
  64.       $optionLinks = $optionSets.find('a');  
  65.   
  66.   $optionLinks.click(function(){  
  67.     var $this = $(this);  
  68.     // don't proceed if already selected  
  69.     if ( $this.hasClass('selected') ) {  
  70.       return false;  
  71.     }  
  72.     var $optionSet = $this.parents('.option-set');  
  73.     $optionSet.find('.selected').removeClass('selected');  
  74.     $this.addClass('selected');  
  75.   
  76.     // make option object dynamically, i.e. { filter: '.my-filter-class' }  
  77.     var options = {},  
  78.         key = $optionSet.attr('data-option-key'),  
  79.         value = $this.attr('data-option-value');  
  80.     // parse 'false' as false boolean  
  81.     value = value === 'false' ? false : value;  
  82.     options[ key ] = value;  
  83.     if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {  
  84.       // changes in layout modes need extra logic  
  85.       changeLayoutMode( $this, options )  
  86.     } else {  
  87.       // otherwise, apply new options  
  88.       $container.isotope( options );  
  89.     }  
  90.       
  91.     return false;  
  92.   });  
  93. );  

显示效果:

选择fitRows后排列效果:

完整demo代码:https://github.com/DaweiCheng/isotope-tutorial/blob/master/layout.html

Isotope中同样可以实现点击element,其中元素动态扩展的效果,即,在运行时,动态改变每个element尺寸;参见代码:https://github.com/DaweiCheng/isotope-tutorial/blob/master/relayout.html

运行显示效果:

点中Li元素之后显示效果:

6. 标记#Hash历史记录

至此,相信读者已经领略到了Isotope显示的动态布局的神奇之处,使用isotope可以实现你意向不到的绚丽的布局和动画效果。但是可否每次记住布局方式,当点击浏览器返回按钮的时候,返回上次观看的布局方式呢?

答案是可以的,借助jQuery另一个插件JQuery BBQ来实现。

jQuery BBQ的官方介绍:jQuery BBQ leverages the HTML5 hashchange event to allow simple, yet powerful bookmarkable #hash history..

首先在HTML页面中加载需要的JavaScript文件

- collapse sourceview plaincopy to clipboardprint?
  1. <script src="js/jquery-1.7.1.min.js"></script>  
  2. <script src="js/jquery.isotope.min.js"></script>  
  3. <script src="js/jquery.ba-bbq.min.js"></script>   

然后我们在option中,将sorting, filtering,layout modes全部添加进来:

- collapse sourceview plaincopy to clipboardprint?
  1. <section id="options" class="clearfix">  
  2.   
  3.   <h3>Filters</h3>  
  4.   
  5.   <ul class="option-set clearfix">  
  6.     <li><a href="#filter=*" class="selected">show all</a></li>  
  7.     <li><a href="#filter=.metal">metal</a></li>  
  8.     <li><a href="#filter=.transition">transition</a></li>  
  9.     <li><a href="#filter=.post-transition">post-transition</a></li>  
  10.     <li><a href="#filter=.nonmetal">nonmetal</a></li>  
  11.     <li><a href="#filter=.inner-transition">inner-transition</a></li>  
  12.     <li><a href="#filter=.alkali%2C+.alkaline-earth">alkali and alkaline-earth</a></li>  
  13.     <li><a href="#filter=%3Anot(.transition)">not transition</a></li>  
  14.     <li><a href="#filter=.metal%3Anot(.transition)">metal but not transition</a></li>  
  15.   </ul>  
  16.   
  17.   <h3>Sort</h3>  
  18.   
  19.   <ul class="option-set clearfix">  
  20.     <li><a href="#sortBy=original-order" class="selected">original-order</a></li>  
  21.     <li><a href="#sortBy=name">name</a></li>  
  22.     <li><a href="#sortBy=symbol">symbol</a></li>  
  23.     <li><a href="#sortBy=number">number</a></li>  
  24.     <li><a href="#sortBy=weight">weight</a></li>  
  25.     <li><a href="#sortBy=category">category</a></li>  
  26.     <li><a href="#sortBy=random">random</a></li>  
  27.   </ul>  
  28.   
  29.   <h3>Sort direction</h3>  
  30.   
  31.   <ul class="option-set clearfix">  
  32.     <li><a href="#sortAscending=true" class="selected">sort ascending</a></li>  
  33.     <li><a href="#sortAscending=false">sort descending</a></li>  
  34.   </ul>  
  35.   
  36.   <h3>Layout modes</h3>  
  37.   
  38.   <ul class="option-set clearfix">  
  39.     <li><a href="#layoutMode=masonry" class="selected">masonry</a></li>  
  40.     <li><a href="#layoutMode=fitRows">fitRows</a></li>  
  41.     <li><a href="#layoutMode=cellsByRow">cellsByRow</a></li>  
  42.     <li><a href="#layoutMode=straightDown">straightDown</a></li>  
  43.   </ul>  
  44.   
  45. </section> <!-- #options -->  

对应的JavaScript代码中,Hash bookmark history部分代码如下,由于篇幅限制,全部JavaScript代码请参见Github中的文件:

- collapse sourceview plaincopy to clipboardprint?
  1. var hashChanged = false;  
  2.   
  3.  $(window).bind( 'hashchange', function( event ){  
  4.    // get options object from hash  
  5.    var hashOptions = window.location.hash ? $.deparam.fragment( window.location.hash, true ) : {},  
  6.        // do not animate first call  
  7.        aniEngine = hashChanged ? 'best-available' : 'none',  
  8.        // apply defaults where no option was specified  
  9.        options = $.extend( {}, defaultOptions, hashOptions, { animationEngine: aniEngine } );  
  10.    // apply options from hash  
  11.    $container.isotope( options );  
  12.    // save options  
  13.    isotopeOptions = hashOptions;  
  14.   
  15.    // if option link was not clicked  
  16.    // then we'll need to update selected links  
  17.    if ( !isOptionLinkClicked ) {  
  18.      // iterate over options  
  19.      var hrefObj, hrefValue, $selectedLink;  
  20.      for ( var key in options ) {  
  21.        hrefObj = {};  
  22.        hrefObj[ key ] = options[ key ];  
  23.        // convert object into parameter string  
  24.        // i.e. { filter: '.inner-transition' } -> 'filter=.inner-transition'  
  25.        hrefValue = $.param( hrefObj );  
  26.        // get matching link  
  27.        $selectedLink = $optionSets.find('a[href="#' + hrefValue + '"]');  
  28.        changeSelectedLink( $selectedLink );  
  29.      }  
  30.    }  
  31.   
  32.    isOptionLinkClicked = false;  
  33.    hashChanged = true;  
  34.  })  
  35.    // trigger hashchange to capture any hash data on init  
  36.    .trigger('hashchange');  

至此就实现了可标记的#hash历史记录,可以记住所有的排版方式,依次进行返回观看前几次的排版样式。

本篇全部示例代码:https://github.com/DaweiCheng/isotope-tutorial 欢迎贡献更多的示例代码。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注