jQuery Masonry + Multiple Stamps + LazyLoad

时间:2015-10-23 20:28:49

标签: jquery jquery-isotope jquery-masonry masonry

我正在尝试创建一个布局,其左上方有一个印章(2x2),右边有2个块(1x1),后面是另一个印章(2x2),右边是第一个印章下面的2个块(1x1)。 简单来说,这是一个简单的问题示例: http://codepen.io/wpsmith/pen/meXoEW

相关:https://github.com/desandro/masonry/issues/779

具体地: 以下是我想要实现的目标:http://bit.ly/1NrOPbj

以下是网站:http://bit.ly/1LrMDjw 以下是代码:http://codepen.io/wpsmith/pen/NGyeoG?editors=001

这是砌体初始化JS代码:

/*! jquery.masonry.init.js 1.0.38
 * http://wpsmith.net
 *
 * Copyright (c) 2015 @wp_smith
 * Available under the MIT license
 */
var WPS = WPS || {};
WPS.masonry = (function ($, window, document) {
    "use strict";

    var app = {
        itemSelector: '.capability-item',
        masonryTO: 250,
        $previousEntry: null,
        resizeTO: 500,
        //context: gjm.context
    };

    /**
     * Caching jQuery elements
     */
    app.cache = function cache() {
        app.$grid = $('.capabilities-container');
        app.$entries = $('.entry');
        app.$images = app.$grid.find('img.not-loaded');
        app.$stamp = app.$grid.find('.stamp');
        app.$stamp1 = app.$grid.find('.stamp-1');
        app.$stamp2 = app.$grid.find('.stamp-2');
        app.$stamp3 = app.$grid.find('.stamp-3');
    };

    /**
     * Create <style> element to be inserted into the header
     */
    app.createStyle = function createStyle() {
        var w = 0;
        // Create the DOM element
        app.style = document.createElement('style');
        app.style.type = 'text/css';
        app.style.id = 'dynamic';

        // Get width (for setting height)
        console.log('----------------------------WIDTH----------------------------');
        //app.width = $(app.$grid.find('.entry:not(.stamp)').get(0)).width();
        console.log('width: ' + $(app.$grid.find('.entry:not(.stamp)').get(0)).width());

        app.width = Math.floor(app.$grid.find('.entry:not(.stamp)').get(0).getBoundingClientRect().width);
        //app.width = Math.floor($(window).width() / 4);
        console.log('width floored: ' + app.width);

        w = app.width / $(window).width() * 100;
        console.log('width percentage: ' + w);
        app.addStylesContent('.grid .one-fourth-full,.grid .grid-item{width:' + w + '% !important;}');
        app.addStylesContent('.grid .featured,.grid .stamp,.grid .entry--width2,.grid .grid-item--width2{width:' + ( w * 2 ) + '% !important;}');

        // Ensure stamps are ready
        app.doStamps();

        // Add style to DOM
        app.appendStyles();
    };

    /**
     * Add custom dynamic styles to style node
     * @param {array} elements Array of jQuery elements
     */
    app.addStyles = function addStyles(elements) {
        var css = '';
        $.each(elements, function (i, e) {
            css += '.grid ' + i + '.grid-item{top:' + e.top + 'px;}';
        });
        app.addStylesContent(css);
    };

    /**
     * Add custom dynamic styles to style node
     * @param {array} elements Array of jQuery elements
     */
    app.addStylesContent = function addStylesContent(content) {
        if (app.style.styleSheet) {
            app.style.styleSheet.cssText = content;
        } else {
            app.style.appendChild(document.createTextNode(content));
        }
    };

    /**
     * Appends dynamic styles to header
     */
    app.appendStyles = function appendStyles() {
        //app.$grid.prepend(app.style);
        document.getElementsByTagName('head')[0].appendChild(app.style);
    };

    /**
     * Remove Style tag.
     */
    app.removeStyles = function removeStyles() {
        $('style#dynamic').remove();
    };

    /**
     * Cycles through the various stamp elements to determine the proper top offset
     * Need CSS4:nth-math
     *
     * @param {array} $stamps Array of jQuery elements.
     * @param {int} offset Offset from top.
     */
    app.doStampStyle = function doStampStyle($stamps, offset) {
        var top = offset || 0,
            elements = {};
        $stamps
            .each(function (i, e) {
                elements['.post-' + $(e).data('id')] = {
                    top: top
                };
                top += app.width;
            });
        app.addStyles(elements);
    };

    /**
     * Performs the dynamic stamp style modifications & ensures the proper height of featured items.
     */
    app.doStamps = function doStamps() {
        var height = 0;
        app.$stamp
            .each(function (i, e) {
                var h = app.width * 2;
                $(e).find('.item').css('height', h);
                $(e)
                    .removeClass('entry')
                    .css({
                        'height': h
                        //'top': height
                    });
                height += app.width;
            });

        app.doStampStyle(app.$stamp1);
        app.doStampStyle(app.$stamp2, app.width);
        app.doStampStyle(app.$stamp3, app.width * 2);
        app.appendStyles();
    };

    /**
     * Initializes everything: cache, doStamps, sets up the grid, initializes masonry, lazy load, & adds eventlisteners
     */
    app.init = function init() {

        // Set cache
        app.cache();

        // Create dynamic style (as opposed to imposing on DOM elements, allowing Masonry to over-ride).
        app.createStyle();

        // Setup Grid
        app.$grid.addClass('grid');
        app.$grid.prepend('<div class="grid-sizer"></div>').prepend('<div class="gutter-sizer"></div>');

        // Remove image sizes
        app.$grid.find('img').attr('width', '').attr('height', '');

        // Let's do the fanciness!
        app.doMasonry();
        app.lazyload();

        // Observe the container
        app.watch();

    };

    /**
     * Triger masonry layout or stamp layout, scroll for lazy load
     * @param {bool|string} type Whether Masonry should be triggered.
     */
    app.trigger = function trigger(type) {
        app.$grid.find('img.not-loaded').trigger('scroll');

        if (type) {
            if ('stamp' === type && false) {
                app.$grid.masonry('stamp', app.$stamp);
            }

            app.$grid.masonry('layout');
        }
    };

    /**
     * Initialize LazyLoad
     */
    app.lazyload = function lazyLoad() {
        app.$images.lazyload({
            effect: 'fadeIn',
            failure_limit: Math.max(app.$images.length - 1, 0),
            threshold: 0,
            load: function () {
                // Disable trigger on this image
                $(this).removeClass("not-loaded");
                //app.$grid.masonry('reload');
                //app.$grid.masonry();
                app.trigger(true);
            }
        });
        //app.$images.trigger('scroll');
        //app.$grid.masonry();
        //$('.item img.not-loaded').trigger('scroll');
    };

    /**
     * Instantiates Masonry.
     */
    app.doMasonry = function doMasonry() {

        var opts = {
            // options
            itemSelector: '.entry',
            columnWidth: app.width, //app.$grid.width() / 4,
            //columnWidth: '.grid-sizer',
            //columnWidth: width, //'.grid-sizer',
            gutter: '.gutter-sizer',
            percentPosition: true,
            isFitWidth: false,
            containerStyle: true,
            isResizeBound: true,
            isInitLayout: false,
            stamp: '.stamp',
            isAnimated: true,
            onLayout: app.trigger
        };
        app.$grid.masonry(opts);

        // bind event
        app.$grid.masonry('once', 'layoutComplete', function () {
            console.log('layout is complete-once');
            $(window).trigger('scroll');
            //$(window).trigger('reload');
            //app.$grid.masonry();
            //app.trigger('stamp');
        });

        // manually trigger initial layout
        app.trigger('stamp');
        //app.$grid.masonry();
    };

    /**
     * Reset Masonry on a small timed event.
     */
    app.resetMasonry = function () {

        // Allow animation, manually call masonry again
        var timeout = setTimeout(function () {

            app.$grid.masonry();
            //app.trigger('stamp');
            clearTimeout(timeout);

        }, app.masonryTO);

    };

    /**
     * Watch masonry & window resizing.
     */
    app.watch = function watch() {
        app.$grid.on('click', '.entry-content, .entry-content .btn.learn', app.entryHandler);
        //$(window).on('resize',app.resize);
    };

    /**
     * onResize event callback.
     *
     * @param event
     */
    app.resize = function onResize(event) {
        app.removeStyles();
        app.createStyle();
    };

    /**
     * Handles click event on non-featured/stamped item to make featured.
     *
     * @param {object} event jQuery event object.
     */
    app.entryHandler = function entryHandler(event) {
        var $entry = $(this).parent('.entry');

        if ($entry.hasClass('view')) {
            return;
        }
        event.preventDefault();
        console.log('click');

        if (app.$previousEntry) {
            app.unfeature(app.$previousEntry);
        }
        app.feature($entry);
    };

    /**
     * Toggles featured classes.
     *
     * @param {obj} $entry jQuery object.
     */
    app.toggleFeature = function ($entry) {
        $entry.toggleClass('featured double entry--width2 entry--height2');
    };

    /**
     * Makes a grid item (entry) unfeatured.
     *
     * @param {obj} $entry jQuery object.
     */
    app.unfeature = function unfeature($entry) {
        var timeout,
            $img = $entry.find('img'),
            $item = $entry.find(app.itemSelector),
            $btn = $entry.find('.btn.view');

        // Remove featured classes
        app.toggleFeature($entry);
        $entry.removeClass('view');
        $btn
            .addClass('learn').removeClass('view')
            .text('Learn More');
        $entry.find('.expand .excerpt').remove();

        // Allow animation, then replace image classes and image size
        timeout = setTimeout(function () {
            $entry.addClass('overlay-grey');
            $item.addClass('overlay-grey');
            $img
                .addClass('greyscale filtered')
                .attr('src', $img.attr('data-thumb'));
            clearTimeout(timeout);

            // Allow animation, manually call masonry again
            app.resetMasonry();

        }, app.resizeTO);
    };

    /**
     * Makes a grid item (entry) featured.
     *
     * @param {obj} $entry jQuery object.
     */
    app.feature = function feature($entry) {
        var timeout,
            $img = $entry.find('img'),
            $item = $entry.find(app.itemSelector),
            $btn = $entry.find('.btn.learn');

        // Add featured classes
        app.toggleFeature($entry);
        $entry.addClass('view');
        $btn
            .removeClass('learn').addClass('view')
            .text($btn.attr('data-view'));
        $entry.find('.expand .h3').after('<p class="excerpt light ' + $item.attr('data-text-color') + '">' + ( $item.attr('data-content') || 'text-white' ) + '</p>');

        // Allow animation, then replace image classes and image size
        timeout = setTimeout(function () {
            $img
                .removeClass('greyscale filtered')
                .attr('src', $img.attr('data-featured'));
            $entry.removeClass('overlay-grey');
            $item.removeClass('overlay-grey');
            clearTimeout(timeout);

            // Allow animation, manually call masonry again
            app.resetMasonry();

            app.$previousEntry = $entry;
        }, app.resizeTO);
    };

    // Let's go!!
    $(document).ready(app.init);

    return app;

})(jQuery, window, document);

代码在网站上运行(在CodePen中,由于某种原因,第一个标记没有正确显示)。但问题是:前两个非印章块出现在邮票下方,而不是在第二个邮票的顶部,如预期的那样。

我相信这是问题所在。印章元素宽度为50%,普通元素宽度为25%。

因此,如果窗口为1583px,则宽度计算为:

  • grid-item:395.75px(app.$grid.find('.entry:not(.stamp)').get(0).getBoundingClientRect().width;
  • .featured.grid-item:791.5px

因此,当砌体进行计算时,一行有四个元素,左边的值是(括号仅指列号,仅供参考):

  • .grid-item(1):left:0
  • .grid-item(2):left:395px
  • .grid-item(3):left:791px
  • .grid-item(4):left:1187px

但如果第一个是特色项目(括号仅指列号仅供参考):

  • .featured.stamp.grid-item(1):left:0
  • .grid-item(3):left:791px
  • .grid-item(4):left:1188px

这使宽度 1px 太宽了!我相信这是jQuery在砌体内进行整理的结果。

0 个答案:

没有答案