以下是 jQuery+CSS3产品360度预览特效 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!doctype html>
<html lang="zh" class="no-js">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery+CSS3产品360度预览特效</title>
<link rel="stylesheet" href="css/reset.css"> <!-- CSS reset -->
<link rel="stylesheet" type="text/css" href="css/zzsc-demo.css">
<link rel="stylesheet" href="css/style2.css"> <!-- Resource style -->
<script src="js/modernizr.js"></script> <!-- Modernizr -->
</head>
<body>
<div class="zzsc-container">
<div class="cd-product-viewer-wrapper" data-frame="16" data-friction="0.33">
<div>
<figure class="product-viewer">
<img src="img/img-loading.jpg" alt="Product Preview">
<div class="product-sprite" data-image="img/img-sprite.png"></div>
</figure> <!-- .product-viewer -->
<div class="cd-product-viewer-handle">
<span class="fill"></span>
<span class="handle">Handle</span>
</div>
</div> <!-- .cd-product-viewer-handle -->
</div> <!-- .cd-product-viewer-wrapper -->
</div>
<script src="js/jquery-2.1.1.min.js" type="text/javascript"></script>
<script src="js/jquery.mobile.custom.min.js"></script>
<script src="js/main.js"></script> <!-- Resource jQuery -->
</body>
</html>
JS代码(main.js):
jQuery(document).ready(function($){
var productViewer = function(element){
this.element = element;
this.handleContainer = this.element.find('.cd-product-viewer-handle');
this.handleFill = this.handleContainer.children('.fill');
this.handle = this.handleContainer.children('.handle');
this.imageWrapper = this.element.find('.product-viewer');
this.slideShow = this.imageWrapper.children('.product-sprite');
this.frames = this.element.data('frame');
//increase this value to increase the friction while dragging on the image - it has to be bigger than zerothis.friction = this.element.data('friction');
this.visibleFrame = 0;
this.loaded = false;
this.animating = false;
this.xPosition = 0;
this.loadFrames();
}
productViewer.prototype.loadFrames = function(){
var self = this,imageUrl = this.slideShow.data('image');
//you need this to check if the image sprite has been loaded$('<img/>').attr('src',imageUrl).load(function(){
self.loaded = true;
}
);
this.loading('0.5');
}
productViewer.prototype.loading = function(percentage){
var self = this;
transformElement(this.handleFill,'scaleX('+ percentage +')');
setTimeout(function(){
if( self.loaded ){
//sprite image has been loadedself.element.addClass('loaded');
transformElement(self.handleFill,'scaleX(1)');
self.dragImage();
if(self.handle) self.dragHandle();
}
else{
//sprite image has not been loaded - increase self.handleFill scale valuevar newPercentage = parseFloat(percentage) + .1;
if ( newPercentage < 1 ){
self.loading(newPercentage);
}
}
}
,500);
}
//draggable funtionality - credits to http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/productViewer.prototype.dragHandle = function(){
//implement handle draggabilityvar self = this;
self.handle.on('mousedown vmousedown',function (e){
self.handle.addClass('cd-draggable');
var dragWidth = self.handle.outerWidth(),containerOffset = self.handleContainer.offset().left,containerWidth = self.handleContainer.outerWidth(),minLeft = containerOffset - dragWidth/2,maxLeft = containerOffset + containerWidth - dragWidth/2;
self.xPosition = self.handle.offset().left + dragWidth - e.pageX;
self.element.on('mousemove vmousemove',function (e){
if( !self.animating){
self.animating = true;
( !window.requestAnimationFrame )? setTimeout(function(){
self.animateDraggedHandle(e,dragWidth,containerOffset,containerWidth,minLeft,maxLeft);
}
,100):requestAnimationFrame(function(){
self.animateDraggedHandle(e,dragWidth,containerOffset,containerWidth,minLeft,maxLeft);
}
);
}
}
).one('mouseup vmouseup',function (e){
self.handle.removeClass('cd-draggable');
self.element.off('mousemove vmousemove');
}
);
e.preventDefault();
}
).on('mouseup vmouseup',function (e){
self.handle.removeClass('cd-draggable');
}
);
}
productViewer.prototype.animateDraggedHandle = function(e,dragWidth,containerOffset,containerWidth,minLeft,maxLeft){
var self = this;
var leftValue = e.pageX + self.xPosition - dragWidth;
// constrain the draggable element to move inside his container if (leftValue < minLeft){
leftValue = minLeft;
}
else if (leftValue > maxLeft){
leftValue = maxLeft;
}
var widthValue = Math.ceil( (leftValue + dragWidth / 2 - containerOffset) * 1000 / containerWidth)/10;
self.visibleFrame = Math.ceil( (widthValue * (self.frames-1))/100 );
//update image frame self.updateFrame();
//update handle position $('.cd-draggable',self.handleContainer).css('left',widthValue + '%').one('mouseup vmouseup',function (){
$(this).removeClass('cd-draggable');
}
);
self.animating = false;
}
productViewer.prototype.dragImage = function(){
//implement image draggabilityvar self = this;
self.slideShow.on('mousedown vmousedown',function (e){
self.slideShow.addClass('cd-draggable');
var containerOffset = self.imageWrapper.offset().left,containerWidth = self.imageWrapper.outerWidth(),minFrame = 0,maxFrame = self.frames - 1;
self.xPosition = e.pageX;
self.element.on('mousemove vmousemove',function (e){
if( !self.animating){
self.animating = true;
( !window.requestAnimationFrame )? setTimeout(function(){
self.animateDraggedImage(e,containerOffset,containerWidth);
}
,100):requestAnimationFrame(function(){
self.animateDraggedImage(e,containerOffset,containerWidth);
}
);
}
}
).one('mouseup vmouseup',function (e){
self.slideShow.removeClass('cd-draggable');
self.element.off('mousemove vmousemove');
self.updateHandle();
}
);
e.preventDefault();
}
).on('mouseup vmouseup',function (e){
self.slideShow.removeClass('cd-draggable');
}
);
}
productViewer.prototype.animateDraggedImage = function(e,containerOffset,containerWidth){
var self = this;
var leftValue = self.xPosition - e.pageX;
var widthValue = Math.ceil( (leftValue) * 100 / ( containerWidth * self.friction ));
var frame = (widthValue * (self.frames-1))/100;
if( frame > 0 ){
frame = Math.floor(frame);
}
else{
frame = Math.ceil(frame);
}
var newFrame = self.visibleFrame + frame;
if (newFrame < 0){
newFrame = self.frames - 1;
}
else if (newFrame > self.frames - 1){
newFrame = 0;
}
if( newFrame != self.visibleFrame ){
self.visibleFrame = newFrame;
self.updateFrame();
self.xPosition = e.pageX;
}
self.animating = false;
}
productViewer.prototype.updateHandle = function(){
if(this.handle){
var widthValue = 100*this.visibleFrame/this.frames;
this.handle.animate({
'left':widthValue + '%'}
,200);
}
}
productViewer.prototype.updateFrame = function(){
var transformValue = - (100 * this.visibleFrame/this.frames);
transformElement(this.slideShow,'translateX('+transformValue+'%)');
}
function transformElement(element,value){
element.css({
'-moz-transform':value,'-webkit-transform':value,'-ms-transform':value,'-o-transform':value,'transform':value,}
);
}
var productToursWrapper = $('.cd-product-viewer-wrapper');
productToursWrapper.each(function(){
new productViewer($(this));
}
);
}
);
CSS代码(reset.css):
/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License:none (public domain)*/
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}
/* HTML5 display-role reset for older browsers */
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,main{display:block;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
table{border-collapse:collapse;border-spacing:0;}
CSS代码(style.css):
/* --------------------------------Primary style-------------------------------- */
html *{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
*,*::after,*::before{box-sizing:border-box;}
html{font-size:62.5%;}
body{font-size:1.6rem;font-family:"Lato",sans-serif;color:#ffffff;background-color:#000000;}
a{color:#b54240;text-decoration:none;}
img{max-width:100%;}
header{position:relative;}
header h1{text-align:center;padding:2em 5%;font-size:2rem;}
@media only screen and (min-width:768px){header h1{font-size:3rem;padding:3em 5% 1em;}
}
@media only screen and (min-width:1170px){header h1{font-weight:300;padding:3em 5% 0;}
}
/* --------------------------------Main Components-------------------------------- */
.cd-product-viewer-wrapper{text-align:center;padding:2em 0;}
.cd-product-viewer-wrapper > div{display:inline-block;}
.cd-product-viewer-wrapper .product-viewer{position:relative;z-index:1;display:inline-block;overflow:hidden;}
.cd-product-viewer-wrapper img{/* this is the image visible before the image sprite is loaded */
display:block;position:relative;z-index:1;}
.cd-product-viewer-wrapper .product-sprite{position:absolute;z-index:2;top:0;left:0;height:100%;/* our image sprite is composed by 16 frames */
width:1600%;background:url(../img/img-sprite.png) no-repeat center center;background-size:100%;opacity:0;-webkit-transition:opacity 0.3s;-moz-transition:opacity 0.3s;transition:opacity 0.3s;}
.cd-product-viewer-wrapper.loaded .product-sprite{/* image sprite has been loaded */
opacity:1;cursor:ew-resize;}
.cd-product-viewer-handle{position:relative;z-index:2;width:60%;max-width:300px;border-radius:50em;margin:1em auto 3em;height:4px;background:#4d4d4d;}
.cd-product-viewer-handle .fill{/* this is used to create the loading fill effect */
position:absolute;z-index:1;left:0;top:0;height:100%;width:100%;border-radius:inherit;background:#b54240;-webkit-transform:scaleX(0);-moz-transform:scaleX(0);-ms-transform:scaleX(0);-o-transform:scaleX(0);transform:scaleX(0);-webkit-transform-origin:left center;-moz-transform-origin:left center;-ms-transform-origin:left center;-o-transform-origin:left center;transform-origin:left center;-webkit-transition:-webkit-transform 0.5s;-moz-transition:-moz-transform 0.5s;transition:transform 0.5s;}
.no-csstransitions .cd-product-viewer-handle .fill{display:none;}
.loaded .cd-product-viewer-handle .fill{/* image sprite has been loaded */
opacity:0;-webkit-transition:-webkit-transform 0.3s,opacity 0.2s 0.3s;-moz-transition:-moz-transform 0.3s,opacity 0.2s 0.3s;transition:transform 0.3s,opacity 0.2s 0.3s;}
.cd-product-viewer-handle .handle{position:absolute;z-index:2;display:inline-block;height:44px;width:44px;left:0;top:-20px;background:#b54240 url(../img/cd-arrows.svg) no-repeat center center;border-radius:50%;box-shadow:0 0 0 6px rgba(181,66,64,0.3),0 0 20px rgba(0,0,0,0.2);/* replace text with image */
text-indent:100%;white-space:nowrap;overflow:hidden;color:transparent;-webkit-transform:translateX(-50%) scale(0);-moz-transform:translateX(-50%) scale(0);-ms-transform:translateX(-50%) scale(0);-o-transform:translateX(-50%) scale(0);transform:translateX(-50%) scale(0);-webkit-transition:box-shadow 0.2s;-moz-transition:box-shadow 0.2s;transition:box-shadow 0.2s;}
.cd-product-viewer-handle .handle:active{box-shadow:0 0 0 0 rgba(181,66,64,0),0 0 20px rgba(0,0,0,0.2);}
.loaded .cd-product-viewer-handle .handle{/* image sprite has been loaded */
-webkit-transform:translateX(-50%) scale(1);-moz-transform:translateX(-50%) scale(1);-ms-transform:translateX(-50%) scale(1);-o-transform:translateX(-50%) scale(1);transform:translateX(-50%) scale(1);-webkit-animation:cd-bounce 0.3s 0.3s;-moz-animation:cd-bounce 0.3s 0.3s;animation:cd-bounce 0.3s 0.3s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;cursor:ew-resize;}
@-webkit-keyframes cd-bounce{0%{-webkit-transform:translateX(-50%) scale(0);}
60%{-webkit-transform:translateX(-50%) scale(1.1);}
100%{-webkit-transform:translateX(-50%) scale(1);}
}
@-moz-keyframes cd-bounce{0%{-moz-transform:translateX(-50%) scale(0);}
60%{-moz-transform:translateX(-50%) scale(1.1);}
100%{-moz-transform:translateX(-50%) scale(1);}
}
@keyframes cd-bounce{0%{-webkit-transform:translateX(-50%) scale(0);-moz-transform:translateX(-50%) scale(0);-ms-transform:translateX(-50%) scale(0);-o-transform:translateX(-50%) scale(0);transform:translateX(-50%) scale(0);}
60%{-webkit-transform:translateX(-50%) scale(1.1);-moz-transform:translateX(-50%) scale(1.1);-ms-transform:translateX(-50%) scale(1.1);-o-transform:translateX(-50%) scale(1.1);transform:translateX(-50%) scale(1.1);}
100%{-webkit-transform:translateX(-50%) scale(1);-moz-transform:translateX(-50%) scale(1);-ms-transform:translateX(-50%) scale(1);-o-transform:translateX(-50%) scale(1);transform:translateX(-50%) scale(1);}
}
CSS代码(style2.css):
/* --------------------------------Primary style-------------------------------- */
html *{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
*,*::after,*::before{box-sizing:border-box;}
html{font-size:62.5%;}
body{font-size:1.6rem;font-family:"Lato",sans-serif;color:#ffffff;background-color:#000000;}
a{color:#b54240;text-decoration:none;}
img{max-width:100%;}
header{position:relative;}
header h1{text-align:center;padding:2em 5%;font-size:2rem;}
@media only screen and (min-width:768px){header h1{font-size:3rem;padding:3em 5% 1em;}
}
@media only screen and (min-width:1170px){header h1{font-weight:300;padding:3em 5% 0;}
}
/* --------------------------------Main Components-------------------------------- */
.cd-product-viewer-wrapper{text-align:center;padding:2em 0;}
.cd-product-viewer-wrapper > div{display:inline-block;}
.cd-product-viewer-wrapper .product-viewer{position:relative;z-index:1;display:inline-block;overflow:hidden;}
.cd-product-viewer-wrapper img{/* this is the image visible before the image sprite is loaded */
display:block;position:relative;z-index:1;}
.cd-product-viewer-wrapper .product-sprite{position:absolute;z-index:2;top:0;left:0;height:100%;/* our image sprite is composed by 16 frames */
width:1600%;background:url(../img/alfa.png) no-repeat center center;background-size:100%;opacity:0;-webkit-transition:opacity 0.3s;-moz-transition:opacity 0.3s;transition:opacity 0.3s;}
.cd-product-viewer-wrapper.loaded .product-sprite{/* image sprite has been loaded */
opacity:1;cursor:ew-resize;}
.cd-product-viewer-handle{position:relative;z-index:2;width:60%;max-width:300px;border-radius:50em;margin:1em auto 3em;height:4px;background:#4d4d4d;}
.cd-product-viewer-handle .fill{/* this is used to create the loading fill effect */
position:absolute;z-index:1;left:0;top:0;height:100%;width:100%;border-radius:inherit;background:#b54240;-webkit-transform:scaleX(0);-moz-transform:scaleX(0);-ms-transform:scaleX(0);-o-transform:scaleX(0);transform:scaleX(0);-webkit-transform-origin:left center;-moz-transform-origin:left center;-ms-transform-origin:left center;-o-transform-origin:left center;transform-origin:left center;-webkit-transition:-webkit-transform 0.5s;-moz-transition:-moz-transform 0.5s;transition:transform 0.5s;}
.no-csstransitions .cd-product-viewer-handle .fill{display:none;}
.loaded .cd-product-viewer-handle .fill{/* image sprite has been loaded */
opacity:0;-webkit-transition:-webkit-transform 0.3s,opacity 0.2s 0.3s;-moz-transition:-moz-transform 0.3s,opacity 0.2s 0.3s;transition:transform 0.3s,opacity 0.2s 0.3s;}
.cd-product-viewer-handle .handle{position:absolute;z-index:2;display:inline-block;height:44px;width:44px;left:0;top:-20px;background:#b54240 url(../img/cd-arrows.svg) no-repeat center center;border-radius:50%;box-shadow:0 0 0 6px rgba(181,66,64,0.3),0 0 20px rgba(0,0,0,0.2);/* replace text with image */
text-indent:100%;white-space:nowrap;overflow:hidden;color:transparent;-webkit-transform:translateX(-50%) scale(0);-moz-transform:translateX(-50%) scale(0);-ms-transform:translateX(-50%) scale(0);-o-transform:translateX(-50%) scale(0);transform:translateX(-50%) scale(0);-webkit-transition:box-shadow 0.2s;-moz-transition:box-shadow 0.2s;transition:box-shadow 0.2s;}
.cd-product-viewer-handle .handle:active{box-shadow:0 0 0 0 rgba(181,66,64,0),0 0 20px rgba(0,0,0,0.2);}
.loaded .cd-product-viewer-handle .handle{/* image sprite has been loaded */
-webkit-transform:translateX(-50%) scale(1);-moz-transform:translateX(-50%) scale(1);-ms-transform:translateX(-50%) scale(1);-o-transform:translateX(-50%) scale(1);transform:translateX(-50%) scale(1);-webkit-animation:cd-bounce 0.3s 0.3s;-moz-animation:cd-bounce 0.3s 0.3s;animation:cd-bounce 0.3s 0.3s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;cursor:ew-resize;}
@-webkit-keyframes cd-bounce{0%{-webkit-transform:translateX(-50%) scale(0);}
60%{-webkit-transform:translateX(-50%) scale(1.1);}
100%{-webkit-transform:translateX(-50%) scale(1);}
}
@-moz-keyframes cd-bounce{0%{-moz-transform:translateX(-50%) scale(0);}
60%{-moz-transform:translateX(-50%) scale(1.1);}
100%{-moz-transform:translateX(-50%) scale(1);}
}
@keyframes cd-bounce{0%{-webkit-transform:translateX(-50%) scale(0);-moz-transform:translateX(-50%) scale(0);-ms-transform:translateX(-50%) scale(0);-o-transform:translateX(-50%) scale(0);transform:translateX(-50%) scale(0);}
60%{-webkit-transform:translateX(-50%) scale(1.1);-moz-transform:translateX(-50%) scale(1.1);-ms-transform:translateX(-50%) scale(1.1);-o-transform:translateX(-50%) scale(1.1);transform:translateX(-50%) scale(1.1);}
100%{-webkit-transform:translateX(-50%) scale(1);-moz-transform:translateX(-50%) scale(1);-ms-transform:translateX(-50%) scale(1);-o-transform:translateX(-50%) scale(1);transform:translateX(-50%) scale(1);}
}