http://www.w2bc.com/article/241859 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jQuery仿Facebook网格图片画廊</title> <style type="text/css"> p { text-align: center; margin: 30px; line-height: 1.5; } .container{padding: 2em 0;} .imgs-grid { max-width: 800px; margin: 0 auto; font-size: 0; } .imgs-grid.imgs-grid-1 .imgs-grid-image { width: 100%; text-align: center; } .imgs-grid.imgs-grid-2 .imgs-grid-image, .imgs-grid.imgs-grid-4 .imgs-grid-image { width: 50%; } .imgs-grid.imgs-grid-3 .imgs-grid-image, .imgs-grid.imgs-grid-6 .imgs-grid-image { width: 33.333333333333336%; } .imgs-grid.imgs-grid-5 .imgs-grid-image:nth-child(1), .imgs-grid.imgs-grid-5 .imgs-grid-image:nth-child(2), .imgs-grid.imgs-grid-5 .imgs-grid-image:nth-child(3) { width: 33.333333333333336%; } .imgs-grid.imgs-grid-5 .imgs-grid-image:nth-child(4), .imgs-grid.imgs-grid-5 .imgs-grid-image:nth-child(5) { width: 50%; } .imgs-grid .imgs-grid-image { position: relative; display: inline-block; padding: 1px; box-sizing: border-box; text-align: center; } .imgs-grid .imgs-grid-image:before { content: ""; display: block; position: absolute; top: 1px; left: 1px; right: 1px; bottom: 1px; background-color: #f0f0f0; } .imgs-grid .imgs-grid-image:hover { cursor: pointer; } .imgs-grid .imgs-grid-image .image-wrap { position: relative; display: inline-block; overflow: hidden; vertical-align: middle; } .imgs-grid .imgs-grid-image .image-wrap img { position: relative; width: 100%; height: auto; margin: 0; } .imgs-grid .imgs-grid-image .view-all { position: absolute; top: 0; left: 0; right: 0; bottom: 0; text-align: center; } .imgs-grid .imgs-grid-image .view-all:before { display: inline-block; content: ""; vertical-align: middle; height: 100%; } .imgs-grid .imgs-grid-image .view-all:hover { cursor: pointer; } .imgs-grid .imgs-grid-image .view-all:hover .view-all-text { text-decoration: underline; } .imgs-grid .imgs-grid-image .view-all .view-all-cover { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: black; opacity: 0.4; } .imgs-grid .imgs-grid-image .view-all .view-all-text { position: relative; font-size: 16px; font-family: sans-serif; color: white; } @media (max-width: 350px) { .imgs-grid .imgs-grid-image .view-all .view-all-text { font-size: 10px; } } .imgs-grid-modal { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background-color: black; opacity: 0; z-index: 100; -webkit-user-select: none; -moz-user-select: -moz-none; -khtml-user-select: none; -o-user-select: none; user-select: none; } .imgs-grid-modal .modal-caption { padding: 30px 50px; text-align: center; color: white; } .imgs-grid-modal .modal-close { position: absolute; right: 10px; top: 10px; width: 35px; height: 35px; background-image: url(http://www.w2bc.com/upload/201705/23/jiaoben5090/src/img/imgs-grid-icons.png); background-repeat: no-repeat; background-position: -100px; } .imgs-grid-modal .modal-close:hover { cursor: pointer; } .imgs-grid-modal .modal-inner { position: absolute; top: 60px; bottom: 60px; left: 0; right: 0; } .imgs-grid-modal .modal-inner .modal-control { position: absolute; top: 0; bottom: 0; width: 70px; } .imgs-grid-modal .modal-inner .modal-control:hover { cursor: pointer; } .imgs-grid-modal .modal-inner .modal-control.left { left: 0; } .imgs-grid-modal .modal-inner .modal-control.right { right: 0; } .imgs-grid-modal .modal-inner .modal-control .arrow { margin: 0 auto; height: 100%; width: 40px; background-repeat: no-repeat; background-image: url(http://www.w2bc.com/upload/201705/23/jiaoben5090/src/img/imgs-grid-icons.png); } .imgs-grid-modal .modal-inner .modal-control .arrow.left { background-position: 2px center; } .imgs-grid-modal .modal-inner .modal-control .arrow.right { background-position: -42px center; } .imgs-grid-modal .modal-inner .modal-image { position: absolute; top: 0; left: 70px; right: 70px; bottom: 0; text-align: center; } .imgs-grid-modal .modal-inner .modal-image:before { display: inline-block; content: ""; vertical-align: middle; height: 100%; } .imgs-grid-modal .modal-inner .modal-image img { max-width: 100%; max-height: 100%; vertical-align: middle; } .imgs-grid-modal .modal-inner .modal-image img:hover { cursor: pointer; } .imgs-grid-modal .modal-inner .modal-loader { display: inline-block; vertical-align: middle; color: silver; font-size: 14px; } @media (max-width: 800px) { .imgs-grid-modal .modal-inner .modal-control { width: 40px; } .imgs-grid-modal .modal-inner .modal-control .arrow { -webkit-transform: scale(0.7); -moz-transform: scale(0.7); -o-transform: scale(0.7); -ms-transform: scale(0.7); transform: scale(0.7); } .imgs-grid-modal .modal-inner .modal-image { left: 0; right: 0; } } .imgs-grid-modal .modal-indicator { position: absolute; bottom: 0; height: 60px; width: 100%; text-align: center; } .imgs-grid-modal .modal-indicator ul { margin: 0; padding: 0; } .imgs-grid-modal .modal-indicator ul li { display: inline-block; width: 12px; height: 12px; border: 1px solid white; box-sizing: border-box; border-radius: 100%; margin: 0 1px; vertical-align: middle; } .imgs-grid-modal .modal-indicator ul li:hover { cursor: pointer; } .imgs-grid-modal .modal-indicator ul li.selected { background-color: white; width: 14px; height: 14px; margin: 0; } </style> </head> <body> <div class="container"> <div id="gallery"></div> </div> </body> <script src="http://cdn.bootcss.com/jquery/1.11.0/jquery.min.js"></script> <script type="text/javascript"> (function($) { /** * Plugin */ $.fn.imagesGrid = function(options) { var args = arguments; return this.each(function() { // If options is plain object - destroy previous instance and create new if ($.isPlainObject(options)) { if (this._imgGrid instanceof ImagesGrid) { this._imgGrid.destroy(); delete this._imgGrid; } var opts = $.extend({}, $.fn.imagesGrid.defaults, options); opts.element = $(this); this._imgGrid = new ImagesGrid(opts); return; } // If options is string - execute method if (typeof options === 'string' && this._imgGrid instanceof ImagesGrid) { switch (options) { case 'modal.open': this._imgGrid.modal.open(args[1]); break; case 'modal.close': this._imgGrid.modal.close(); break; case 'destroy': this._imgGrid.destroy(); delete this._imgGrid; break; } } }); }; /** * Plugin default options */ $.fn.imagesGrid.defaults = { images: [], cells: 6, align: false, nextOnClick: true, showViewAll: 'more', viewAllStartIndex: 'auto', getViewAllText: function(imagesCount) { return 'View all ' + imagesCount + ' images'; }, onGridRendered: $.noop, onGridItemRendered: $.noop, onGridLoaded: $.noop, onGridImageLoaded: $.noop, onModalOpen: $.noop, onModalClose: $.noop, onModalImageClick: $.noop, onModalImageUpdate: $.noop }; /** * ImagesGrid * opts - Grid options * opts.element - Element where to render images grid * opts.images - Array of images. Array item can be string or object { src, alt, title, caption, thumbnail } * opts.align - Align images with different height * opts.cells - Maximum number of cells (from 1 to 6) * opts.showViewAll - Show view all text: * 'more' - show if number of images greater than number of cells * 'always' - always show * false - never show * opts.viewAllStartIndex - Start image index when view all link clicked * opts.getViewAllText - Callback function returns text for "view all images" link * opts.onGridRendered - Callback function fired when grid items added to the DOM * opts.onGridItemRendered - Callback function fired when grid item added to the DOM * opts.onGridLoaded - Callback function fired when grid images loaded * opts.onGridImageLoaded - Callback function fired when grid image loaded */ function ImagesGrid(opts) { this.opts = opts || {}; this.$window = $(window); this.$element = this.opts.element; this.$gridItems = []; this.modal = null; this.imageLoadCount = 0; var cells = this.opts.cells; this.opts.cells = (cells < 1)? 1: (cells > 6)? 6: cells; this.onWindowResize = this.onWindowResize.bind(this); this.onImageClick = this.onImageClick.bind(this); this.init(); } ImagesGrid.prototype.init = function() { this.setGridClass(); this.renderGridItems(); this.createModal(); this.$window.on('resize', this.onWindowResize); } ImagesGrid.prototype.createModal = function() { var opts = this.opts; this.modal = new ImagesGridModal({ images: opts.images, nextOnClick: opts.nextOnClick, onModalOpen: opts.onModalOpen, onModalClose: opts.onModalClose, onModalImageClick: opts.onModalImageClick, onModalImageUpdate: opts.onModalImageUpdate }); } ImagesGrid.prototype.setGridClass = function() { var opts = this.opts, imgsLen = opts.images.length, cellsCount = (imgsLen < opts.cells)? imgsLen: opts.cells; this.$element.addClass('imgs-grid imgs-grid-' + cellsCount); } ImagesGrid.prototype.renderGridItems = function() { var opts = this.opts, imgs = opts.images, imgsLen = imgs.length; if (!imgs) { return; } this.$element.empty(); this.$gridItems = []; for (var i = 0; i < imgsLen; ++i) { if (i === opts.cells) { break; } this.renderGridItem(imgs[i], i); } if (opts.showViewAll === 'always' || (opts.showViewAll === 'more' && imgsLen > opts.cells) ) { this.renderViewAll(); } opts.onGridRendered(this.$element); } ImagesGrid.prototype.renderGridItem = function(image, index) { var src = image, alt = '', title = '', opts = this.opts, _this = this; if ($.isPlainObject(image)) { src = image.thumbnail || image.src; alt = image.alt || ''; title = image.title || ''; } var item = $('<div>', { class: 'imgs-grid-image', click: this.onImageClick, data: { index: index } }); item.append( $('<div>', { class: 'image-wrap' }).append( $('<img>', { src: src, alt: alt, title: title, on: { load: function(event) { _this.onImageLoaded(event, $(this), image); } } }) ) ); this.$gridItems.push(item); this.$element.append(item); opts.onGridItemRendered(item, image); } ImagesGrid.prototype.renderViewAll = function() { var opts = this.opts; this.$element.find('.imgs-grid-image:last .image-wrap').append( $('<div>', { class: 'view-all' }).append( $('<span>', { class: 'view-all-cover', }), $('<span>', { class: 'view-all-text', text: opts.getViewAllText(opts.images.length) }) ) ); } ImagesGrid.prototype.onWindowResize = function(event) { if (this.opts.align) { this.align(); } } ImagesGrid.prototype.onImageClick = function(event) { var opts = this.opts, img = $(event.currentTarget), imageIndex; if (img.find('.view-all').length > 0 && typeof opts.viewAllStartIndex === 'number' ) { imageIndex = opts.viewAllStartIndex; } else { imageIndex = img.data('index'); } this.modal.open(imageIndex); } ImagesGrid.prototype.onImageLoaded = function(event, imageEl, image) { var opts = this.opts; ++this.imageLoadCount; opts.onGridImageLoaded(event, imageEl, image); if (this.imageLoadCount === this.$gridItems.length) { this.imageLoadCount = 0; this.onAllImagesLoaded() } } ImagesGrid.prototype.onAllImagesLoaded = function() { var opts = this.opts; if (opts.align) { this.align(); } opts.onGridLoaded(this.$element); } ImagesGrid.prototype.align = function() { var itemsLen = this.$gridItems.length; switch (itemsLen) { case 2: case 3: this.alignItems(this.$gridItems); break; case 4: this.alignItems(this.$gridItems.slice(0, 2)); this.alignItems(this.$gridItems.slice(2)); break; case 5: case 6: this.alignItems(this.$gridItems.slice(0, 3)); this.alignItems(this.$gridItems.slice(3)); break; } } ImagesGrid.prototype.alignItems = function(items) { var itemsHeight = items.map(function(item) { return item.find('img').height(); }); var normalizedHeight = Math.min.apply(null, itemsHeight); $(items).each(function() { var item = $(this), imgWrap = item.find('.image-wrap'), img = item.find('img'), imgHeight = img.height(); imgWrap.height(normalizedHeight); if (imgHeight > normalizedHeight) { var top = Math.floor((imgHeight - normalizedHeight) / 2); img.css({ top: -top }); } }); } ImagesGrid.prototype.destroy = function() { this.$window.off('resize',this.onWindowResize); this.$element.empty() .removeClass('imgs-grid imgs-grid-' + this.$gridItems.length); this.modal.destroy(); } /** * ImagesGridModal * opts - Modal options * opts.images - Array of images * opts.nextOnClick - Show next image when click on modal image * opts.onModalOpen - Callback function called when modal opened * opts.onModalClose - Callback function called when modal closed * opts.onModalImageClick - Callback function called on modal image click */ function ImagesGridModal(opts) { this.opts = opts || {}; this.imageIndex = null; this.$document = $(document); this.$modal = null; this.$indicator = null; this.close = this.close.bind(this); this.prev = this.prev.bind(this); this.next = this.next.bind(this); this.onIndicatorClick = this.onIndicatorClick.bind(this); this.onImageLoaded = this.onImageLoaded.bind(this); this.onKeyUp = this.onKeyUp.bind(this); this.$document.on('keyup', this.onKeyUp); } ImagesGridModal.prototype.open = function(imageIndex) { if (this.isOpened()) { return; } this.imageIndex = parseInt(imageIndex) || 0; this.render(); } ImagesGridModal.prototype.close = function(event) { if (!this.$modal) { return; } var opts = this.opts; this.$modal.animate({ opacity: 0 }, { duration: 100, complete: function() { this.$modal.remove(); this.$modal = null; this.$indicator = null; this.imageIndex = null; opts.onModalClose(); }.bind(this) }); } ImagesGridModal.prototype.isOpened = function() { return (this.$modal && this.$modal.is(':visible')); } ImagesGridModal.prototype.render = function() { var opts = this.opts; this.renderModal(); this.renderCaption(); this.renderCloseButton(); this.renderInnerContainer(); this.renderIndicatorContainer(); this.$modal.animate({ opacity: 1 }, { duration: 100, complete: function() { opts.onModalOpen(this.$modal, opts.images[this.imageIndex]); }.bind(this) }); } ImagesGridModal.prototype.renderModal = function() { this.$modal = $('<div>', { class: 'imgs-grid-modal' }).appendTo('body'); } ImagesGridModal.prototype.renderCaption = function() { this.$caption = $('<div>', { class: 'modal-caption', text: this.getImageCaption(this.imageIndex) }).appendTo(this.$modal); } ImagesGridModal.prototype.renderCloseButton = function() { this.$modal.append($('<div>', { class: 'modal-close', click: this.close })); } ImagesGridModal.prototype.renderInnerContainer = function() { var opts = this.opts, image = this.getImage(this.imageIndex); this.$modal.append( $('<div>', { class: 'modal-inner' }).append( $('<div>', { class: 'modal-image' }).append( $('<img>', { src: image.src, alt: image.alt, title: image.title, on: { load: this.onImageLoaded, click: function(event) { this.onImageClick(event, $(this), image); }.bind(this) } }), $('<div>', { class: 'modal-loader', text: 'loading...' }) ), $('<div>', { class: 'modal-control left', click: this.prev }).append( $('<div>', { class: 'arrow left' }) ), $('<div>', { class: 'modal-control right', click: this.next }).append( $('<div>', { class: 'arrow right' }) ) ) ); if (opts.images.length <= 1) { this.$modal.find('.modal-control').hide(); } } ImagesGridModal.prototype.renderIndicatorContainer = function() { var opts = this.opts, imgsLen = opts.images.length; if (imgsLen == 1) { return; } this.$indicator = $('<div>', { class: 'modal-indicator' }); var list = $('<ul>'), i; for (i = 0; i < imgsLen; ++i) { list.append($('<li>', { class: this.imageIndex == i? 'selected': '', click: this.onIndicatorClick, data: { index: i } })); } this.$indicator.append(list); this.$modal.append(this.$indicator); } ImagesGridModal.prototype.prev = function() { var imgsLen = this.opts.images.length; if (this.imageIndex > 0) { --this.imageIndex; } else { this.imageIndex = imgsLen - 1; } this.updateImage(); } ImagesGridModal.prototype.next = function() { var imgsLen = this.opts.images.length; if (this.imageIndex < imgsLen - 1) { ++this.imageIndex; } else { this.imageIndex = 0; } this.updateImage(); } ImagesGridModal.prototype.updateImage = function() { var opts = this.opts, image = this.getImage(this.imageIndex), imageEl = this.$modal.find('.modal-image img'); imageEl.attr({ src: image.src, alt: image.alt, title: image.title }); this.$modal.find('.modal-caption').text( this.getImageCaption(this.imageIndex) ); if (this.$indicator) { var indicatorList = this.$indicator.find('ul'); indicatorList.children().removeClass('selected'); indicatorList.children().eq(this.imageIndex).addClass('selected'); } this.showLoader(); opts.onModalImageUpdate(imageEl, image); } ImagesGridModal.prototype.onImageClick = function(event, imageEl, image) { var opts = this.opts; if (opts.nextOnClick) { this.next(); } opts.onModalImageClick(event, imageEl, image); } ImagesGridModal.prototype.onImageLoaded = function() { this.hideLoader(); } ImagesGridModal.prototype.onIndicatorClick = function(event) { var index = $(event.target).data('index'); this.imageIndex = index; this.updateImage(); } ImagesGridModal.prototype.onKeyUp = function(event) { if (!this.$modal) { return; } switch (event.keyCode) { case 27: // Esc this.close(); break; case 37: // Left arrow this.prev(); break; case 39: // Right arrow this.next(); break; } } ImagesGridModal.prototype.getImage = function(index) { var opts = this.opts, image = opts.images[index]; if ($.isPlainObject(image)) { return image; } else { return { src: image, alt: '', title: '' } } } ImagesGridModal.prototype.getImageCaption = function(imgIndex) { var img = this.getImage(imgIndex); return img.caption || ''; } ImagesGridModal.prototype.showLoader = function() { if (this.$modal) { this.$modal.find('.modal-image img').hide(); this.$modal.find('.modal-loader').show(); } } ImagesGridModal.prototype.hideLoader = function() { if (this.$modal) { this.$modal.find('.modal-image img').show(); this.$modal.find('.modal-loader').hide(); } } ImagesGridModal.prototype.destroy = function() { this.$document.off('keyup', this.onKeyUp); this.close(); } })(jQuery); </script> <script> $('#gallery').imagesGrid({ images: [ { src: 'http://img2.xcabc.com/201707/04/20170704011703830950.jpg', thumbnail: 'http://img2.xcabc.com/201707/04/20170704011703830950.jpg' }, { src: 'http://img2.xcabc.com/201706/23/20170623011535065538.jpg', alt: 'Nature', title: 'Nature' }, 'http://img2.xcabc.com/201706/23/20170623011120236825.jpg', { src: 'http://img2.xcabc.com/201706/20/20170620022700562971.jpg', caption: 'The long way' }, 'http://img2.xcabc.com/201706/17/20170617023215784843.jpg', 'http://img2.xcabc.com/201706/14/20170614052148876339.jpg', 'http://img2.xcabc.com/201706/06/20170606054205719520.jpg', 'http://img2.xcabc.com/201706/14/20170614050140121872.jpg' ], align: true }); </script> </html> 提示:你可以先修改部分代码再运行。 转载请注明:有爱前端 » jQuery仿Facebook网格图片画廊 喜欢 (1)or分享 (0)