以下是 瀑布流排版鼠标点击放大图片代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"content="width=device-width, initial-scale=1">
<title>瀑布流排版鼠标点击放大图片代码</title>
<link rel="stylesheet" type="text/css" href="css/style1.css" />
<script src="js/modernizr-custom.js"></script>
</head>
<body class="demo-1">
<div class="container">
<div class="content">
<div class="grid">
<div class="grid__item" data-size="1280x853"> <a href="images/weix/1.png" class="img-wrap"><img src="images/weix/1.png" alt="img1" />
<div class="description description--grid">Assemblage</div>
</a> </div>
<div class="grid__item" data-size="958x1280"> <a href="images/weix/2.png" class="img-wrap"><img src="images/weix/2.png" alt="img2" />
<div class="description description--grid">Demesne</div>
</a> </div>
<div class="grid__item" data-size="1280x853"> <a href="images/weix/3.png" class="img-wrap"><img src="images/weix/3.png" alt="img3" />
<div class="description description--grid">Vestigial</div>
</a> </div>
<div class="grid__item" data-size="865x1280"> <a href="images/weix/4.png" class="img-wrap"><img src="images/weix/4.png" alt="img4" />
<div class="description description--grid">Zephyr</div>
</a> </div>
<div class="grid__item" data-size="1280x1280"> <a href="images/weix/5.png" class="img-wrap"><img src="images/weix/5.png" alt="img5" />
<div class="description description--grid">Desideratum</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/6.png" class="img-wrap"><img src="images/weix/6.png" alt="img6" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/7.png" class="img-wrap"><img src="images/weix/7.png" alt="img7" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/8.png" class="img-wrap"><img src="images/weix/8.png" alt="img8" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/9.png" class="img-wrap"><img src="images/weix/9.png" alt="img9" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/1.png" class="img-wrap"><img src="images/weix/1.png" alt="img10" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/2.png" class="img-wrap"><img src="images/weix/2.png" alt="img11" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/3.png" class="img-wrap"><img src="images/weix/3.png" alt="img12" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/4.png" class="img-wrap"><img src="images/weix/4.png" alt="img13" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/5.png" class="img-wrap"><img src="images/weix/5.png" alt="img14" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/6.png" class="img-wrap"><img src="images/weix/6.png" alt="img15" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/7.png" class="img-wrap"><img src="images/weix/7.png" alt="img16" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/8.png" class="img-wrap"><img src="images/weix/8.png" alt="img17" />
<div class="description description--grid">Quixotic</div>
</a> </div>
<div class="grid__item" data-size="1280x850"> <a href="images/weix/9.png" class="img-wrap"><img src="images/weix/9.png" alt="img18" />
<div class="description description--grid">Quixotic</div>
</a> </div>
</div>
<!-- /grid -->
<div class="preview">
<button class="action action--close"><i class="fa fa-times">x</i><span class="text-hidden">Close</span></button>
<div class="description description--preview"></div>
</div>
<!-- /preview -->
</div>
</div>
<!-- /container -->
<script src="js/imagesloaded.pkgd.min.js"></script>
<script src="js/masonry.pkgd.min.js"></script>
<script src="js/classie.js"></script>
<script src="js/main.js"></script>
<script>
(function() {
// create SVG circle overlay and append it to the preview element
function createCircleOverlay(previewEl) {
var dummy = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
dummy.setAttributeNS(null, 'version', '1.1');
dummy.setAttributeNS(null, 'width', '100%');
dummy.setAttributeNS(null, 'height', '100%');
dummy.setAttributeNS(null, 'class', 'overlay');
var g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttributeNS(null, 'cx', 0);
circle.setAttributeNS(null, 'cy', 0);
circle.setAttributeNS(null, 'r', Math.sqrt(Math.pow(previewEl.offsetWidth,2) + Math.pow(previewEl.offsetHeight,2)));
dummy.appendChild(g);
g.appendChild(circle);
previewEl.appendChild(dummy);
}
new GridFx(document.querySelector('.grid'), {
onInit : function(instance) {
createCircleOverlay(instance.previewEl);
},
onResize : function(instance) {
instance.previewEl.querySelector('svg circle').setAttributeNS(null, 'r', Math.sqrt(Math.pow(instance.previewEl.offsetWidth,2) + Math.pow(instance.previewEl.offsetHeight,2)));
},
onOpenItem : function(instance, item) {
// item's image
var gridImg = item.querySelector('img'),
gridImgOffset = gridImg.getBoundingClientRect(),
win = {width: document.documentElement.clientWidth, height: window.innerHeight},
SVGCircleGroupEl = instance.previewEl.querySelector('svg > g'),
SVGCircleEl = SVGCircleGroupEl.querySelector('circle');
SVGCircleEl.setAttributeNS(null, 'r', Math.sqrt(Math.pow(instance.previewEl.offsetWidth,2) + Math.pow(instance.previewEl.offsetHeight,2)));
// set the transform for the SVG g node. This will animate the circle overlay. The origin of the circle depends on the position of the clicked item.
if( gridImgOffset.left + gridImg.offsetWidth/2 < win.width/2 ) {
SVGCircleGroupEl.setAttributeNS(null, 'transform', 'translate(' + win.width + ', ' + (gridImgOffset.top + gridImg.offsetHeight/2 < win.height/2 ? win.height : 0) + ')');
}
else {
SVGCircleGroupEl.setAttributeNS(null, 'transform', 'translate(0, ' + (gridImgOffset.top + gridImg.offsetHeight/2 < win.height/2 ? win.height : 0) + ')');
}
}
});
})();
</script>
</body>
</html>
JS代码(classie.js):
/*! * classie v1.0.1 * class helper functions * from bonzo https://github.com/ded/bonzo * MIT license * * classie.has( elem,'my-class' ) -> true/false * classie.add( elem,'my-new-class' ) * classie.remove( elem,'my-unwanted-class' ) * classie.toggle( elem,'my-class' ) */
/*jshint browser:true,strict:true,undef:true,unused:true */
/*global define:false,module:false */
( function( window ){
'use strict';
// class helper functions from bonzo https://github.com/ded/bonzofunction classReg( className ){
return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
}
// classList support for class management// altho to be fair,the api sucks because it won't accept multiple classes at oncevar hasClass,addClass,removeClass;
if ( 'classList' in document.documentElement ){
hasClass = function( elem,c ){
return elem.classList.contains( c );
}
;
addClass = function( elem,c ){
elem.classList.add( c );
}
;
removeClass = function( elem,c ){
elem.classList.remove( c );
}
;
}
else{
hasClass = function( elem,c ){
return classReg( c ).test( elem.className );
}
;
addClass = function( elem,c ){
if ( !hasClass( elem,c ) ){
elem.className = elem.className + ' ' + c;
}
}
;
removeClass = function( elem,c ){
elem.className = elem.className.replace( classReg( c ),' ' );
}
;
}
function toggleClass( elem,c ){
var fn = hasClass( elem,c ) ? removeClass:addClass;
fn( elem,c );
}
var classie ={
// full names hasClass:hasClass,addClass:addClass,removeClass:removeClass,toggleClass:toggleClass,// short names has:hasClass,add:addClass,remove:removeClass,toggle:toggleClass}
;
// transportif ( typeof define === 'function' && define.amd ){
// AMD define( classie );
}
else if ( typeof exports === 'object' ){
// CommonJS module.exports = classie;
}
else{
// browser global window.classie = classie;
}
}
)( window );
JS代码(main.js):
;
(function(window){
'use strict';
var support ={
transitions:Modernizr.csstransitions}
,// transition end event nametransEndEventNames ={
'WebkitTransition':'webkitTransitionEnd','MozTransition':'transitionend','OTransition':'oTransitionEnd','msTransition':'MSTransitionEnd','transition':'transitionend'}
,transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],onEndTransition = function( el,callback ){
var onEndCallbackFn = function( ev ){
if( support.transitions ){
if( ev.target != this ) return;
this.removeEventListener( transEndEventName,onEndCallbackFn );
}
if( callback && typeof callback === 'function' ){
callback.call(this);
}
}
;
if( support.transitions ){
el.addEventListener( transEndEventName,onEndCallbackFn );
}
else{
onEndCallbackFn();
}
}
;
/** * some helper functions */
function throttle(fn,delay){
var allowSample = true;
return function(e){
if (allowSample){
allowSample = false;
setTimeout(function(){
allowSample = true;
}
,delay);
fn(e);
}
}
;
}
function nextSibling(el){
var nextSibling = el.nextSibling;
while(nextSibling && nextSibling.nodeType != 1){
nextSibling = nextSibling.nextSibling}
return nextSibling;
}
function extend( a,b ){
for( var key in b ){
if( b.hasOwnProperty( key ) ){
a[key] = b[key];
}
}
return a;
}
/** * GridFx obj */
function GridFx(el,options){
this.gridEl = el;
this.options = extend({
}
,this.options );
extend( this.options,options );
this.items = [].slice.call(this.gridEl.querySelectorAll('.grid__item'));
this.previewEl = nextSibling(this.gridEl);
this.isExpanded = false;
this.isAnimating = false;
this.closeCtrl = this.previewEl.querySelector('button.action--close');
this.previewDescriptionEl = this.previewEl.querySelector('.description--preview');
this._init();
}
/** * options */
GridFx.prototype.options ={
pagemargin:0,// x and y can have values from 0 to 1 (percentage). If negative then it means the alignment is left and/or top rather than right and/or bottom// so,as an example,if we want our large image to be positioned vertically on 25% of the screen and centered horizontally the values would be x:1,y:-0.25imgPosition:{
x:1,y:1}
,onInit:function(instance){
return false;
}
,onResize:function(instance){
return false;
}
,onOpenItem:function(instance,item){
return false;
}
,onCloseItem:function(instance,item){
return false;
}
,onExpand:function(){
return false;
}
}
GridFx.prototype._init = function(){
// callbackthis.options.onInit(this);
var self = this;
// init masonry after all images are loadedimagesLoaded( this.gridEl,function(){
// initialize masonrynew Masonry(self.gridEl,{
itemSelector:'.grid__item',isFitWidth:true}
);
// show grid after all images (thumbs) are loadedclassie.add(self.gridEl,'grid--loaded');
// init/bind eventsself._initEvents();
// create the large image and append it to the DOMself._setOriginal();
// create the clone image and append it to the DOMself._setClone();
}
);
}
;
/** * initialize/bind events */
GridFx.prototype._initEvents = function (){
var self = this,clickEvent = (document.ontouchstart!==null ? 'click':'touchstart');
this.items.forEach(function(item){
var touchend = function(ev){
ev.preventDefault();
self._openItem(ev,item);
item.removeEventListener('touchend',touchend);
}
,touchmove = function(ev){
item.removeEventListener('touchend',touchend);
}
,manageTouch = function(){
item.addEventListener('touchend',touchend);
item.addEventListener('touchmove',touchmove);
}
;
item.addEventListener(clickEvent,function(ev){
if(clickEvent === 'click'){
ev.preventDefault();
self._openItem(ev,item);
}
else{
manageTouch();
}
}
);
}
);
// close expanded imagethis.closeCtrl.addEventListener('click',function(){
self._closeItem();
}
);
window.addEventListener('resize',throttle(function(ev){
// callbackself.options.onResize(self);
}
,10));
}
/** * open a grid item */
GridFx.prototype._openItem = function(ev,item){
if( this.isAnimating || this.isExpanded ) return;
this.isAnimating = true;
this.isExpanded = true;
// item's imagevar gridImg = item.querySelector('img'),gridImgOffset = gridImg.getBoundingClientRect();
// index of current itemthis.current = this.items.indexOf(item);
// set the src of the original image element (large image)this._setOriginal(item.querySelector('a').getAttribute('href'));
// callbackthis.options.onOpenItem(this,item);
// set the clone imagethis._setClone(gridImg.src,{
width:gridImg.offsetWidth,height:gridImg.offsetHeight,left:gridImgOffset.left,top:gridImgOffset.top}
);
// hide original grid itemclassie.add(item,'grid__item--current');
// calculate the transform value for the clone to animate to the full image viewvar win = this._getWinSize(),originalSizeArr = item.getAttribute('data-size').split('x'),originalSize ={
width:originalSizeArr[0],height:originalSizeArr[1]}
,dx = ((this.options.imgPosition.x > 0 ? 1-Math.abs(this.options.imgPosition.x):Math.abs(this.options.imgPosition.x)) * win.width + this.options.imgPosition.x * win.width/2) - gridImgOffset.left - 0.5 * gridImg.offsetWidth,dy = ((this.options.imgPosition.y > 0 ? 1-Math.abs(this.options.imgPosition.y):Math.abs(this.options.imgPosition.y)) * win.height + this.options.imgPosition.y * win.height/2) - gridImgOffset.top - 0.5 * gridImg.offsetHeight,z = Math.min( Math.min(win.width*Math.abs(this.options.imgPosition.x) - this.options.pagemargin,originalSize.width - this.options.pagemargin)/gridImg.offsetWidth,Math.min(win.height*Math.abs(this.options.imgPosition.y) - this.options.pagemargin,originalSize.height - this.options.pagemargin)/gridImg.offsetHeight );
// apply transform to the clonethis.cloneImg.style.WebkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0) scale3d(' + z + ',' + z + ',1)';
this.cloneImg.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0) scale3d(' + z + ',' + z + ',1)';
// add the description if anyvar descriptionEl = item.querySelector('.description');
if( descriptionEl ){
this.previewDescriptionEl.innerHTML = descriptionEl.innerHTML;
}
var self = this;
setTimeout(function(){
// controls the elements inside the expanded viewclassie.add(self.previewEl,'preview--open');
// callbackself.options.onExpand();
}
,0);
// after the clone animates..onEndTransition(this.cloneImg,function(){
// when the original/large image is loaded..imagesLoaded(self.originalImg,function(){
// close button just gets shown after the large image gets loadedclassie.add(self.previewEl,'preview--image-loaded');
// animate the opacity to 1self.originalImg.style.opacity = 1;
// and once that's done..onEndTransition(self.originalImg,function(){
// reset cloneImgself.cloneImg.style.opacity = 0;
self.cloneImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
self.cloneImg.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
self.isAnimating = false;
}
);
}
);
}
);
}
;
/** * create/set the original/large image element */
GridFx.prototype._setOriginal = function(src){
if( !src ){
this.originalImg = document.createElement('img');
this.originalImg.className = 'original';
this.originalImg.style.opacity = 0;
this.originalImg.style.maxWidth = 'calc(' + parseInt(Math.abs(this.options.imgPosition.x)*100) + 'vw - ' + this.options.pagemargin + 'px)';
this.originalImg.style.maxHeight = 'calc(' + parseInt(Math.abs(this.options.imgPosition.y)*100) + 'vh - ' + this.options.pagemargin + 'px)';
// need it because of firefoxthis.originalImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
this.originalImg.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
src = '';
this.previewEl.appendChild(this.originalImg);
}
this.originalImg.setAttribute('src',src);
}
;
/** * create/set the clone image element */
GridFx.prototype._setClone = function(src,settings){
if( !src ){
this.cloneImg = document.createElement('img');
this.cloneImg.className = 'clone';
src = '';
this.cloneImg.style.opacity = 0;
this.previewEl.appendChild(this.cloneImg);
}
else{
this.cloneImg.style.opacity = 1;
// set top/left/width/height of grid item's image to the clonethis.cloneImg.style.width = settings.width + 'px';
this.cloneImg.style.height = settings.height + 'px';
this.cloneImg.style.top = settings.top + 'px';
this.cloneImg.style.left = settings.left + 'px';
}
this.cloneImg.setAttribute('src',src);
}
;
/** * closes the original/large image view */
GridFx.prototype._closeItem = function(){
if( !this.isExpanded || this.isAnimating ) return;
this.isExpanded = false;
this.isAnimating = true;
// the grid item's image and its offsetvar gridItem = this.items[this.current],gridImg = gridItem.querySelector('img'),gridImgOffset = gridImg.getBoundingClientRect(),self = this;
classie.remove(this.previewEl,'preview--open');
classie.remove(this.previewEl,'preview--image-loaded');
// callbackthis.options.onCloseItem(this,gridItem);
// large image will animate back to the position of its grid's itemclassie.add(this.originalImg,'animate');
// set the transform to the original/large imagevar win = this._getWinSize(),dx = gridImgOffset.left + gridImg.offsetWidth/2 - ((this.options.imgPosition.x > 0 ? 1-Math.abs(this.options.imgPosition.x):Math.abs(this.options.imgPosition.x)) * win.width + this.options.imgPosition.x * win.width/2),dy = gridImgOffset.top + gridImg.offsetHeight/2 - ((this.options.imgPosition.y > 0 ? 1-Math.abs(this.options.imgPosition.y):Math.abs(this.options.imgPosition.y)) * win.height + this.options.imgPosition.y * win.height/2),z = gridImg.offsetWidth/this.originalImg.offsetWidth;
this.originalImg.style.WebkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0) scale3d(' + z + ',' + z + ',1)';
this.originalImg.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0) scale3d(' + z + ',' + z + ',1)';
// once that's done..onEndTransition(this.originalImg,function(){
// clear descriptionself.previewDescriptionEl.innerHTML = '';
// show original grid itemclassie.remove(gridItem,'grid__item--current');
// fade out the original imagesetTimeout(function(){
self.originalImg.style.opacity = 0;
}
,60);
// and after thatonEndTransition(self.originalImg,function(){
// reset original/large imageclassie.remove(self.originalImg,'animate');
self.originalImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
self.originalImg.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
self.isAnimating = false;
}
);
}
);
}
;
/** * gets the window sizes */
GridFx.prototype._getWinSize = function(){
return{
width:document.documentElement.clientWidth,height:window.innerHeight}
;
}
;
window.GridFx = GridFx;
}
)(window);
CSS代码(style1.css):
body{background-color:#000000}
.grid{position:relative;margin:0 auto;}
.js .grid::after{content:'';position:absolute;width:100%;height:100%;top:0;left:0;pointer-events:none;background-size:60px auto;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;}
.js .grid--loaded::after{opacity:0;}
.grid__item{width:270px;padding:10px;}
.grid__item--current{opacity:0 !important;}
.img-wrap{display:block;}
.img-wrap:focus,.img-wrap:hover{outline:none;}
.img-wrap img{display:block;max-width:100%;}
.preview{position:fixed;z-index:1000;top:0;left:0;display:-webkit-flex;display:-ms-flex;display:flex;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;width:100%;height:100%;pointer-events:none;}
.preview--open{pointer-events:auto;}
/* circle overlay (generated SVG) */
.overlay{position:absolute;top:0;left:0;pointer-events:none;}
.overlay circle{-webkit-transition:fill-opacity 0.3s,-webkit-transform 0s 0.3s;transition:fill-opacity 0.3s,transform 0s 0.3s;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out;-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1);fill:#1f1d1d;fill-opacity:0;}
.preview--open .overlay circle{-webkit-transition:-webkit-transform 0.4s;transition:transform 0.4s;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);fill-opacity:1;}
.clone{position:fixed;z-index:110;-webkit-transition:-webkit-transform 0.6s cubic-bezier(0.5,1,0.2,1);transition:transform 0.6s cubic-bezier(0.5,1,0.2,1);-webkit-backface-visibility:hidden;}
.original{position:relative;z-index:120;display:block;object-fit:contain;-webkit-transition:opacity 0.2s;transition:opacity 0.2s;-webkit-backface-visibility:hidden;}
.preview--open .animate{/* open */
-webkit-transition:-webkit-transform 0.6s,opacity 0.2s;transition:transform 0.6s,opacity 0.2s;}
.animate{/* close */
-webkit-transition:-webkit-transform 0.3s,opacity 0.2s;transition:transform 0.3s,opacity 0.2s;}
.description{color:#fff;}
.js .description--grid{display:none;}
.description--preview{position:fixed;z-index:140;bottom:0;left:0;width:100%;padding:2em 1em;text-align:center;opacity:0;background:linear-gradient(180deg,transparent,#1f1d1d);-webkit-transition:opacity 0.3s,-webkit-transform 0.3s;transition:opacity 0.3s,transform 0.3s;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);}
.preview--open .description--preview{opacity:1;-webkit-transition-delay:0.2s;transition-delay:0.2s;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);}
/* Close button */
.action{font-size:1.5em;margin:0;padding:0;cursor:pointer;vertical-align:top;color:#6bd68a;border:none;background:none;}
.action:hover,.action:focus{color:#6bd68a;outline:none;}
.action--close{position:fixed;z-index:150;top:0;right:0;padding:1em;opacity:0;-webkit-transition:opacity 0.3s,-webkit-transform 0.3s;transition:opacity 0.3s,transform 0.3s;-webkit-transform:scale3d(0.6,0.6,1);transform:scale3d(0.6,0.6,1);}
.preview--image-loaded .action--close{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);}
.text-hidden{position:absolute;display:block;overflow:hidden;width:0;height:0;color:transparent;}