现在网上很流行瀑布流,jquery插件,我昨天也学习别别人做的,但是不知道怎么修改瀑布流的列数。求大神 指导。  
插件代码如下 /**
 * jQuery Masonry v2.1.03
 * A dynamic layout plugin for jQuery
 * The flip-side of CSS Floats
 * http://masonry.desandro.com
 *
 * Licensed under the MIT license.
 * Copyright 2011 David DeSandro
 *//*jshint browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */
/*global jQuery: false */(function( window, $, undefined ){  'use strict';  /*
   * smartresize: debounced resize event for jQuery
   *
   * latest version and complete README available on Github:
   * https://github.com/louisremi/jquery.smartresize.js
   *
   * Copyright 2011 @louis_remi
   * Licensed under the MIT license.
   */  var $event = $.event,
      resizeTimeout;  $event.special.smartresize = {
    setup: function() {
      $(this).bind( "resize", $event.special.smartresize.handler );
    },
    teardown: function() {
      $(this).unbind( "resize", $event.special.smartresize.handler );
    },
    handler: function( event, execAsap ) {
      // Save the context
      var context = this,
          args = arguments;      // set correct event type
      event.type = "smartresize";      if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
      resizeTimeout = setTimeout(function() {
        jQuery.event.handle.apply( context, args );
      }, execAsap === "execAsap"? 0 : 100 );
    }
  };  $.fn.smartresize = function( fn ) {
    return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
  };// ========================= Masonry ===============================
  // our "Widget" object constructor
  $.Mason = function( options, element ){
    this.element = $( element );    this._create( options );
    this._init();
  };  $.Mason.settings = {
    isResizable: true,
    isAnimated: false,
    animationOptions: {
      queue: false,
      duration: 500
    },
    gutterWidth: 0,
    isRTL: false,
    isFitWidth: false,
    containerStyle: {
      position: 'relative'
    }
  };  $.Mason.prototype = {    _filterFindBricks: function( $elems ) {
      var selector = this.options.itemSelector;
      // if there is a selector
      // filter/find appropriate item elements
      return !selector ? $elems : $elems.filter( selector ).add( $elems.find( selector ) );
    },    _getBricks: function( $elems ) {
      var $bricks = this._filterFindBricks( $elems )
        .css({ position: 'absolute' })
        .addClass('masonry-brick');
      return $bricks;
    },
    
    // sets up widget
    _create : function( options ) {
      
      this.options = $.extend( true, {}, $.Mason.settings, options );
      this.styleQueue = [];      // get original styles in case we re-apply them in .destroy()
      var elemStyle = this.element[0].style;
      this.originalStyle = {
        // get height
        height: elemStyle.height || ''
      };
      // get other styles that will be overwritten
      var containerStyle = this.options.containerStyle;
      for ( var prop in containerStyle ) {
        this.originalStyle[ prop ] = elemStyle[ prop ] || '';
      }      this.element.css( containerStyle );      this.horizontalDirection = this.options.isRTL ? 'right' : 'left';      this.offset = {
        x: parseInt( this.element.css( 'padding-' + this.horizontalDirection ),10),
        y: parseInt( this.element.css( 'padding-top' ), 10 )
      };
      //console.log(this.offset.y);
      this.isFluid = this.options.columnWidth && typeof this.options.columnWidth === 'function';      // add masonry class first time around
      var instance = this;
      setTimeout( function() {
        instance.element.addClass('masonry');
      }, 0 );
      
      // bind resize method
      if ( this.options.isResizable ) {
        $(window).bind( 'smartresize.masonry', function() { 
          instance.resize();
        });
      }
      // need to get bricks
      this.reloadItems();    },
  
    // _init fires when instance is first created
    // and when instance is triggered again -> $el.masonry();
    _init : function( callback ) {
      this._getColumns();
      this._reLayout( callback );
    },    option: function( key, value ){
      // set options AFTER initialization:
      // signature: $('#foo').bar({ cool:false });
      if ( $.isPlainObject( key ) ){
        this.options = $.extend(true, this.options, key);
      } 
    },
    
    // ====================== General Layout ======================    // used on collection of atoms (should be filtered, and sorted before )
    // accepts atoms-to-be-laid-out to start with
    layout : function( $bricks, callback ) {      // place each brick
      for (var i=0, len = $bricks.length; i < len; i++) {
        this._placeBrick( $bricks[i] );
      }
      
      // set the size of the container
      var containerSize = {};
      containerSize.height = Math.max.apply( Math, this.colYs );
      if ( this.options.isFitWidth ) {
        var unusedCols = 0;
        i = this.cols;
        // count unused columns
        while ( --i ) {
          if ( this.colYs[i] !== 0 ) {
            break;
          }
          unusedCols++;
        }
        // fit container to columns that have been used;
        containerSize.width = (this.cols - unusedCols) * this.columnWidth - this.options.gutterWidth;
      }
      this.styleQueue.push({ $el: this.element, style: containerSize });
      // are we animating the layout arrangement?
      // use plugin-ish syntax for css or animate
      var styleFn = !this.isLaidOut ? 'css' : (
            this.options.isAnimated ? 'animate' : 'css'
          ),
          animOpts = this.options.animationOptions;      // process styleQueue
      var obj;
      for (i=0, len = this.styleQueue.length; i < len; i++) {
        obj = this.styleQueue[i];
        obj.$el[ styleFn ]( obj.style, animOpts );
      }      // clear out queue for next time
      this.styleQueue = [];      // provide $elems as context for the callback
      if ( callback ) {
        callback.call( $bricks );
      }
      
      this.isLaidOut = true;
    },
    
    // calculates number of columns
    // i.e. this.columnWidth = 200
    _getColumns : function() {
      var container = this.options.isFitWidth ? this.element.parent() : this.element,
          containerWidth = container.width();                         // use fluid columnWidth function if there
      this.columnWidth = this.isFluid ? this.options.columnWidth( containerWidth ) :
                    // if not, how about the explicitly set option?
                    this.options.columnWidth ||
                    // or use the size of the first item
                    this.$bricks.outerWidth(true) ||
                    // if there's no items, use size of container
                    containerWidth;      this.columnWidth += this.options.gutterWidth;      this.cols = Math.floor( ( containerWidth + this.options.gutterWidth ) / this.columnWidth );
      this.cols = Math.max( this.cols, 4);    },    // layout logic
    _placeBrick: function( brick ) {
      var $brick = $(brick),
          colSpan, groupCount, groupY, groupColY, j;      //how many columns does this brick span
      colSpan = Math.ceil( $brick.outerWidth(true) /
        ( this.columnWidth + this.options.gutterWidth ) );
      colSpan = Math.min( colSpan, this.cols );      if ( colSpan === 1 ) {
        // if brick spans only one column, just like singleMode
        groupY = this.colYs;
      } else {
        // brick spans more than one column
        // how many different places could this brick fit horizontally
        groupCount = this.cols + 1 - colSpan;
        groupY = [];        // for each group potential horizontal position
        for ( j=0; j < groupCount; j++ ) {
          // make an array of colY values for that one group
          groupColY = this.colYs.slice( j, j+colSpan );
          // and get the max value of the array
          groupY[j] = Math.max.apply( Math, groupColY );
        }      }      // get the minimum Y value from the columns
      var minimumY = Math.min.apply( Math, groupY ),
          shortCol = 0;
      //console.log(Math);
      // Find index of short column, the first from the left
      for (var i=0, len = groupY.length; i < len; i++) {
        if ( groupY[i] === minimumY ) {
          shortCol = i;
          break;
        }
      }      // position the brick
      var position = {
        top: minimumY + this.offset.y
      };
      // position.left or position.right
      position[ this.horizontalDirection ] = this.columnWidth * shortCol + this.offset.x;
  
  
 jQuery瀑布流

解决方案 »

  1.   

    接上面代码    this.styleQueue.push({ $el: $brick, style: position });      // apply setHeight to necessary columns
          var setHeight = minimumY + $brick.outerHeight(true),
              setSpan = this.cols + 1 - len;
          for ( i=0; i < setSpan; i++ ) {
            this.colYs[ shortCol + i ] = setHeight;
          }    },
        
        
        resize: function() {
          var prevColCount = this.cols;
          // get updated colCount
          this._getColumns();
          if ( this.isFluid || this.cols !== prevColCount ) {
            // if column count has changed, trigger new layout
            this._reLayout();
          }
        },
        
        
        _reLayout : function( callback ) {
          // reset columns
          var i = this.cols;
          this.colYs = [];
          while (i--) {
            this.colYs.push( 0 );
          }
          // apply layout logic to all bricks
          this.layout( this.$bricks, callback );
        },
        
        // ====================== Convenience methods ======================
        
        // goes through all children again and gets bricks in proper order
        reloadItems : function() {
          this.$bricks = this._getBricks( this.element.children() );
        },
        
        
        reload : function( callback ) {
          this.reloadItems();
          this._init( callback );
        },
            // convienence method for working with Infinite Scroll
        appended : function( $content, isAnimatedFromBottom, callback ) {
          if ( isAnimatedFromBottom ) {
            // set new stuff to the bottom
            this._filterFindBricks( $content ).css({ top: this.element.height() });
            var instance = this;
            setTimeout( function(){
              instance._appended( $content, callback );
            }, 1 );
          } else {
            this._appended( $content, callback );
          }
        
        
        _appended : function( $content, callback ) {
          var $newBricks = this._getBricks( $content );
          // add new bricks to brick pool
          this.$bricks = this.$bricks.add( $newBricks );
          this.layout( $newBricks, callback );
        },
        
        // removes elements from Masonry widget
        remove : function( $content ) {
          this.$bricks = this.$bricks.not( $content );
          $content.remove();
        },
        
        // destroys widget, returns elements and container back (close) to original style
        destroy : function() {      this.$bricks
            .removeClass('masonry-brick')
            .each(function(){
              this.style.position = '';
              this.style.top = '';
              this.style.left = '';
            });
          
          // re-apply saved container styles
          var elemStyle = this.element[0].style;
          for ( var prop in this.originalStyle ) {
            elemStyle[ prop ] = this.originalStyle[ prop ];
          }      this.element
            .unbind('.masonry')
            .removeClass('masonry')
            .removeData('masonry');
          
          $(window).unbind('.masonry');    }
        
      };
      
      
      // ======================= imagesLoaded Plugin ===============================
      /*!
       * jQuery imagesLoaded plugin v1.1.0
       * http://github.com/desandro/imagesloaded
       *
       * MIT License. by Paul Irish et al.
       */
      // $('#my-container').imagesLoaded(myFunction)
      // or
      // $('img').imagesLoaded(myFunction)  // execute a callback when all images have loaded.
      // needed because .load() doesn't work on cached images  // callback function gets image collection as argument
      //  `this` is the container  $.fn.imagesLoaded = function( callback ) {
        var $this = this,
            $images = $this.find('img').add( $this.filter('img') ),
            len = $images.length,
            blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
            loaded = [];    function triggerCallback() {
          callback.call( $this, $images );
        }    function imgLoaded( event ) {
          var img = event.target;
          if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){
            loaded.push( img );
            if ( --len <= 0 ){
              setTimeout( triggerCallback );
              $images.unbind( '.imagesLoaded', imgLoaded );
            }
          }
        }    // if no images, trigger immediately
        if ( !len ) {
          triggerCallback();
        }    $images.bind( 'load.imagesLoaded error.imagesLoaded',  imgLoaded ).each( function() {
          // cached images don't fire load sometimes, so we reset src.
          var src = this.src;
          // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
          // data uri bypasses webkit log warning (thx doug jones)
          this.src = blank;
          this.src = src;
        });    return $this;
      };
      // helper function for logging errors
      // $.error breaks jQuery chaining
      var logError = function( message ) {
        if ( window.console ) {
          window.console.error( message );
        }
      };
      
      // =======================  Plugin bridge  ===============================
      // leverages data method to either create or return $.Mason constructor
      // A bit from jQuery UI
      //   https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
      // A bit from jcarousel 
      //   https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js  $.fn.masonry = function( options ) {
        if ( typeof options === 'string' ) {
          // call method
          var args = Array.prototype.slice.call( arguments, 1 );      this.each(function(){
            var instance = $.data( this, 'masonry' );
            if ( !instance ) {
              logError( "cannot call methods on masonry prior to initialization; " +
                "attempted to call method '" + options + "'" );
              return;
            }
            if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
              logError( "no such method '" + options + "' for masonry instance" );
              return;
            }
            // apply method
            instance[ options ].apply( instance, args );
          });
        } else {
          this.each(function() {
            var instance = $.data( this, 'masonry' );
            if ( instance ) {
              // apply options & init
              instance.option( options || {} );
              instance._init();
            } else {
              // initialize new instance
              $.data( this, 'masonry', new $.Mason( options, this ) );
            }
          });
        }
        return this;
      };})( window, jQuery );},