jQuery仿Facebook网格图片画廊
发布时间:2017-06-05, 10:07:14 分类:HTML | 编辑 off 网址 | 辅助
图集1/8
正文 25719字数 376,626阅读
<style>
/*images-grid.css*/
.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(https://out.img.pan.lizhenqiu.com/cd84c407eea1508b56a93b050e0dba7f1496628404000);
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(https://out.img.pan.lizhenqiu.com/cd84c407eea1508b56a93b050e0dba7f1496628404000);
}
.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>
<style type="text/css">
p {
text-align: center;
margin: 30px;
line-height: 1.5;
}
.container{padding: 2em 0;}
</style>
<div class="container">
<div id="gallery"></div>
</div>
<script src="https://lizhenqiu.com/templates/default/jquery.min.js"></script>
<script>
//images-grid.js
(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: 5,
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: 'https://out.img.pan.lizhenqiu.com/408ed4061b8d35480169f97e2e414e26', thumbnail: 'https://out.img.pan.lizhenqiu.com/408ed4061b8d35480169f97e2e414e26' },
{ src: 'https://out.img.pan.lizhenqiu.com/86f740e5196bec328ee09cca4dd9c827', alt: 'Nature', title: 'Nature' },
'https://out.img.pan.lizhenqiu.com/51794a1a2130d362ec06d13b0527a3d5',
{ src: 'http://li.img.pan.lizhenqiu.com/c12b16fa4ad93da983c10afb7bc7476a.gif', caption: 'The long way' },
'http://li.img.pan.lizhenqiu.com/72fee818c257249f887a5501f334f8e8.jpg',
'http://li.img.pan.lizhenqiu.com/3869f49ea223dc148d0051e27672f02b.jpg',
'http://li.img.pan.lizhenqiu.com/bb281cc082242fb8bbff93111e7924fd.jpg'
],
align: true
});
</script>
Run code
Cut to clipboard
(支付宝)给作者钱财以资鼓励 (微信)→
有过 7 条评论 »
—鲁迅《拿来主义》