以下是 14款CSS3卡片堆叠切换动画特效代码 的示例演示效果:
部分效果截图:
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.0">
<title>14款CSS3卡片堆叠切换动画特效</title>
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
<link rel="stylesheet" type="text/css" href="fonts/font-awesome-4.3.0/css/font-awesome.min.css" />
<link rel="stylesheet" type="text/css" href="css/default.css" />
<link rel="stylesheet" type="text/css" href="css/component.css" />
<script src="js/modernizr-custom.js"></script>
</head>
<body>
<div class="container">
<div class="content color-1">
<h2 class="content__title">Yuda</h2>
<ul id="stack_yuda" class="stack stack--yuda">
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_yuda"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_yuda"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-2">
<h2 class="content__title">Krisna</h2>
<ul id="stack_krisna" class="stack stack--krisna">
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_krisna"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_krisna"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-3">
<h2 class="content__title">Wangi</h2>
<ul id="stack_wangi" class="stack stack--wangi">
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_wangi"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_wangi"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-4">
<h2 class="content__title">Wira</h2>
<ul id="stack_wira" class="stack stack--wira">
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_wira"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_wira"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-5">
<h2 class="content__title">Slamet</h2>
<div class="counter" id="counter">
<svg width="40" height="40" viewBox="0 0 60 60">
<path d="M55.215 8.397c-0.336-1.32-1.968-2.397-3.63-2.397h-43.17c-1.665 0-3.297 1.077-3.63 2.397l-0.603 3.603h51.633l-0.6-3.603zM58.236 15h-56.475c-1.026 0-1.827 0.882-1.731 1.905l2.769 35.007c0.114 1.182 1.11 2.088 2.298 2.088h49.803c1.191 0 2.184-0.906 2.298-2.088l2.769-35.007c0.099-1.023-0.705-1.905-1.731-1.905zM37.314 25.125c1.554 0 2.814 1.26 2.814 2.814s-1.26 2.814-2.814 2.814-2.814-1.263-2.814-2.817c0-1.551 1.26-2.811 2.814-2.811zM16.5 42l7.458-17.142 8.481 13.728 7.272-3.612 3.789 7.026h-27z"></path>
</svg>
<span class="text-hidden">Saved Images</span>
<span class="counter__number">0</span>
</div>
<ul id="stack_slamet" class="stack stack--slamet">
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_slamet"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_slamet"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-6">
<h2 class="content__title">Utari</h2>
<ul id="stack_utari" class="stack stack--utari">
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_utari"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_utari"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-7">
<h2 class="content__title">Cinta</h2>
<ul id="stack_cinta" class="stack stack--cinta">
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_cinta"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_cinta"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-8">
<h2 class="content__title">Eka</h2>
<ul id="stack_eka" class="stack stack--eka">
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_eka"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_eka"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-1">
<h2 class="content__title">Dian</h2>
<ul id="stack_dian" class="stack stack--dian">
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_dian"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_dian"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-6">
<h2 class="content__title">Iman</h2>
<ul id="stack_iman" class="stack stack--iman">
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_iman"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_iman"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-3">
<h2 class="content__title">Iskandar</h2>
<ul id="stack_iskandar" class="stack stack--iskandar">
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_iskandar"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_iskandar"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-5">
<h2 class="content__title">Kasih</h2>
<ul id="stack_kasih" class="stack stack--kasih">
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_kasih"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_kasih"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<div class="content color-2">
<h2 class="content__title">Buana</h2>
<ul id="stack_buana" class="stack stack--buana">
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
</ul>
<div class="controls">
<button class="button button--material button--reject" data-stack="stack_buana"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--material button--accept" data-stack="stack_buana"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
<div class="material-circle"></div>
</div>
<div class="content color-6">
<h2 class="content__title">Mawar</h2>
<ul id="stack_mawar" class="stack stack--mawar">
<li class="stack__item"><img src="img/8.png" alt="Tree 8" /></li>
<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
<li class="stack__item"><img src="img/7.png" alt="Tree 7" /></li>
<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
</ul>
<div class="controls">
<button class="button button--sonar button--reject" data-stack="stack_mawar"><i class="fa fa-times"></i><span class="text-hidden">Reject</span></button>
<button class="button button--sonar button--accept" data-stack="stack_mawar"><i class="fa fa-check"></i><span class="text-hidden">Accept</span></button>
</div>
</div>
<!-- Related demos -->
</div><!-- /container -->
<script src="js/classie.js"></script>
<!--
click feedback effect : see more at http://tympanus.net/codrops/2015/02/11/subtle-click-feedback-effects/
-->
<script>
// http://stackoverflow.com/a/11381730/989439
function mobilecheck() {
var check = false;
(function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
var clickeventtype = mobilecheck() ? 'touchstart' : 'click';
(function() {
var support = { animations : Modernizr.cssanimations },
animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' },
animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
onEndAnimation = function( el, callback ) {
var onEndCallbackFn = function( ev ) {
if( support.animations ) {
if(ev.target != this) return;
this.removeEventListener( animEndEventName, onEndCallbackFn);
}
if(callback && typeof callback === 'function') {callback.call();}
};
if( support.animations ) {
el.addEventListener(animEndEventName, onEndCallbackFn);
}
else {
onEndCallbackFn();
}
};
[].slice.call(document.querySelectorAll('.button--sonar')).forEach(function(el) {
el.addEventListener(clickeventtype, function(ev) {
if( el.getAttribute('data-state') !== 'locked' ) {
classie.add(el, 'button--active');
onEndAnimation(el, function() {
classie.remove(el, 'button--active');
});
}
});
});
})();
</script>
<script src="js/dynamics.min.js"></script>
<script src="js/main.js"></script>
<script>
(function() {
var support = { animations : Modernizr.cssanimations },
animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' },
animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
onEndAnimation = function( el, callback ) {
var onEndCallbackFn = function( ev ) {
if( support.animations ) {
if(ev.target != this) return;
this.removeEventListener( animEndEventName, onEndCallbackFn);
}
if(callback && typeof callback === 'function') {callback.call();}
};
if( support.animations ) {
el.addEventListener(animEndEventName, onEndCallbackFn);
}
else {
onEndCallbackFn();
}
};
function nextSibling(el) {
var nextSibling = el.nextSibling;
while(nextSibling && nextSibling.nodeType != 1) {
nextSibling = nextSibling.nextSibling
}
return nextSibling;
}
var yuda = new Stack(document.getElementById('stack_yuda')),
krisna = new Stack(document.getElementById('stack_krisna')),
wangi = new Stack(document.getElementById('stack_wangi')),
wira = new Stack(document.getElementById('stack_wira')),
utari = new Stack(document.getElementById('stack_utari'), {
stackItemsAnimationDelay: 240,
stackItemsAnimation : {
duration : 360,
type : dynamics.bezier,
points : [{'x':0,'y':0,'cp':[{'x':0.4,'y':1}]},{'x':1,'y':1,'cp':[{'x':0.3,'y':1}]}]
},
}),
slamet = new Stack(document.getElementById('stack_slamet'), {
infinite: false,
perspective: 1400,
onEndStack: function(instance) {
setTimeout(function() {
instance.restart();
document.querySelector('#counter > .counter__number').innerHTML = 0;
}, 300);
}
}),
cinta = new Stack(document.getElementById('stack_cinta'), {
perspective: 1400,
perspectiveOrigin: '200% -100%',
visible: 6,
infinite: false,
onEndStack: function(instance) {
setTimeout(function() {
instance.restart();
}, 300);
}
}),
eka = new Stack(document.getElementById('stack_eka'), {
stackItemsAnimation : {
duration: 800,
type: dynamics.spring
}
}),
dian = new Stack(document.getElementById('stack_dian'), {
stackItemsAnimationDelay : 100,
stackItemsAnimation : {
duration: 800,
type: dynamics.spring,
},
visible: 1,
perspectiveOrigin: '50% 50%'
}),
iman = new Stack(document.getElementById('stack_iman'), {
stackItemsAnimation : {
duration: 800,
type: dynamics.spring
},
stackItemsPreAnimation : {
accept : {
elastic: true,
animationProperties: {translateX : 100, translateY : 10, rotateZ: 5},
animationSettings: {
duration: 100,
type: dynamics.easeIn
}
},
reject : {
elastic: true,
animationProperties: {translateX : -100, translateY : 10, rotateZ: -5},
animationSettings: {
duration: 100,
type: dynamics.easeIn
}
}
}
}),
iskandar = new Stack(document.getElementById('stack_iskandar'), {
stackItemsAnimation : {
duration: 800,
type: dynamics.spring
},
perspectiveOrigin : '50% 130%',
visible: 5,
stackItemsPreAnimation : {
accept : {
elastic: true,
animationProperties: {translateX : 150, translateY : -10},
animationSettings: {
duration: 200,
type: dynamics.easeOut
}
}
}
}),
kasih = new Stack(document.getElementById('stack_kasih'), {
stackItemsAnimation : {
duration: 1300,
type: dynamics.spring,
friction: 420,
},
visible: 4,
perspectiveOrigin : '50% 50%',
stackItemsPreAnimation : {
accept : {
elastic: true,
animationProperties: {translateX : 250},
animationSettings: {
duration: 400,
type: dynamics.easeIn
}
},
reject : {
elastic: true,
animationProperties: {translateX : -250},
animationSettings: {
duration: 400,
type: dynamics.easeIn
}
}
}
}),
buana = new Stack(document.getElementById('stack_buana'), {
perspectiveOrigin : '-50% -50%'
}),
mawar = new Stack(document.getElementById('stack_mawar'), {
perspective : 1500,
perspectiveOrigin : '-150% 50%',
visible: 4,
stackItemsAnimation : {
duration: 1300,
type: dynamics.spring
},
stackItemsPreAnimation : {
accept : {
elastic: true,
animationProperties: {translateX : 100},
animationSettings: {
duration: 200,
type: dynamics.easeIn
}
},
reject : {
elastic: true,
animationProperties: {translateX : -100},
animationSettings: {
duration: 200,
type: dynamics.easeIn
}
}
}
});
// controls the click ring effect on the button
var buttonClickCallback = function(bttn) {
var bttn = bttn || this;
bttn.setAttribute('data-state', 'unlocked');
};
document.querySelector('.button--accept[data-stack = stack_yuda]').addEventListener(clickeventtype, function() { yuda.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_yuda]').addEventListener(clickeventtype, function() { yuda.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_krisna]').addEventListener(clickeventtype, function() { krisna.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_krisna]').addEventListener(clickeventtype, function() { krisna.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_wangi]').addEventListener(clickeventtype, function() { wangi.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_wangi]').addEventListener(clickeventtype, function() { wangi.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_wira]').addEventListener(clickeventtype, function() { wira.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_wira]').addEventListener(clickeventtype, function() { wira.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_utari]').addEventListener(clickeventtype, function() { utari.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_utari]').addEventListener(clickeventtype, function() { utari.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_slamet]').addEventListener(clickeventtype, function(ev) {
var callback = function() {
// increment counter
var counter = document.querySelector('#counter > .counter__number'),
count = parseInt(counter.innerHTML);
counter.innerHTML = count + 1;
buttonClickCallback(ev.target);
};
slamet.accept(callback);
});
document.querySelector('.button--reject[data-stack = stack_slamet]').addEventListener(clickeventtype, function() { slamet.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_cinta]').addEventListener(clickeventtype, function() { cinta.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_cinta]').addEventListener(clickeventtype, function() { cinta.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_eka]').addEventListener(clickeventtype, function() { eka.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_eka]').addEventListener(clickeventtype, function() { eka.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_dian]').addEventListener(clickeventtype, function() { dian.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_dian]').addEventListener(clickeventtype, function() { dian.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_iman]').addEventListener(clickeventtype, function() { iman.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_iman]').addEventListener(clickeventtype, function() { iman.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_iskandar]').addEventListener(clickeventtype, function() { iskandar.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_iskandar]').addEventListener(clickeventtype, function() { iskandar.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_kasih]').addEventListener(clickeventtype, function() { kasih.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_kasih]').addEventListener(clickeventtype, function() { kasih.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_buana]').addEventListener(clickeventtype, function() { buana.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_buana]').addEventListener(clickeventtype, function() { buana.reject(buttonClickCallback.bind(this)); });
document.querySelector('.button--accept[data-stack = stack_mawar]').addEventListener(clickeventtype, function() { mawar.accept(buttonClickCallback.bind(this)); });
document.querySelector('.button--reject[data-stack = stack_mawar]').addEventListener(clickeventtype, function() { mawar.reject(buttonClickCallback.bind(this)); });
[].slice.call(document.querySelectorAll('.button--sonar')).forEach(function(bttn) {
bttn.addEventListener(clickeventtype, function() {
bttn.setAttribute('data-state', 'locked');
});
});
[].slice.call(document.querySelectorAll('.button--material')).forEach(function(bttn) {
var radialAction = nextSibling(bttn.parentNode);
bttn.addEventListener(clickeventtype, function(ev) {
var boxOffset = radialAction.parentNode.getBoundingClientRect(),
offset = bttn.getBoundingClientRect();
radialAction.style.left = Number(offset.left - boxOffset.left) + 'px';
radialAction.style.top = Number(offset.top - boxOffset.top) + 'px';
classie.add(radialAction, classie.has(bttn, 'button--reject') ? 'material-circle--reject' : 'material-circle--accept');
classie.add(radialAction, 'material-circle--active');
onEndAnimation(radialAction, function() {
classie.remove(radialAction, classie.has(bttn, 'button--reject') ? 'material-circle--reject' : 'material-circle--accept');
classie.remove(radialAction, 'material-circle--active');
});
});
});
})();
</script>
</body>
</html>
JS代码(main.js):
/** * main.js * http://www.codrops.com * * Licensed under the MIT license. * http://www.opensource.org/licenses/mit-license.php * * Copyright 2015,Codrops * http://www.codrops.com */
;
(function(window){
'use strict';
var support ={
animations:Modernizr.cssanimations}
,animEndEventNames ={
'WebkitAnimation':'webkitAnimationEnd','OAnimation':'oAnimationEnd','msAnimation':'MSAnimationEnd','animation':'animationend'}
,animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],onEndAnimation = function( el,callback ){
var onEndCallbackFn = function( ev ){
if( support.animations ){
if( ev.target != this ) return;
this.removeEventListener( animEndEventName,onEndCallbackFn );
}
if( callback && typeof callback === 'function' ){
callback.call();
}
}
;
if( support.animations ){
el.addEventListener( animEndEventName,onEndCallbackFn );
}
else{
onEndCallbackFn();
}
}
;
function extend( a,b ){
for( var key in b ){
if( b.hasOwnProperty( key ) ){
a[key] = b[key];
}
}
return a;
}
function Stack(el,options){
this.el = el;
this.options = extend({
}
,this.options );
extend( this.options,options );
this.items = [].slice.call(this.el.children);
this.itemsTotal = this.items.length;
if( this.options.infinite && this.options.visible >= this.itemsTotal || !this.options.infinite && this.options.visible > this.itemsTotal || this.options.visible <=0 ){
this.options.visible = 1;
}
this.current = 0;
this._init();
}
Stack.prototype.options ={
// stack's perspective valueperspective:1000,// stack's perspective originperspectiveOrigin:'50% -50%',// number of visible items in the stackvisible:3,// infinite navigationinfinite:true,// callback:when reaching the end of the stackonEndStack:function(){
return false;
}
,// animation settings for the items' movements in the stack when the items rearrange// object that is passed to the dynamicsjs animate function (see more at http://dynamicsjs.com/)// example://{
type:dynamics.spring,duration:1641,frequency:557,friction:459,anticipationSize:206,anticipationStrength:392}
stackItemsAnimation:{
duration:500,type:dynamics.bezier,points:[{
'x':0,'y':0,'cp':[{
'x':0.25,'y':0.1}
]}
,{
'x':1,'y':1,'cp':[{
'x':0.25,'y':1}
]}
]}
,// delay for the items' rearrangement / delay before stackItemsAnimation is appliedstackItemsAnimationDelay:0,// animation settings for the items' movements in the stack before the rearrangement// we can set up different settings depending on whether we are approving or rejecting an item/*stackItemsPreAnimation:{
reject:{
// if true,then the settings.properties parameter will be distributed through the items in a non equal fashion// for instance,if we set settings.properties ={
translateX:100}
and we have options.visible = 4,// then the second item in the stack will translate 100px,the second one 75px and the third 50pxelastic:true,// object that is passed into the dynamicsjs animate function - second parameter - (see more at http://dynamicsjs.com/)animationProperties:{
}
,// object that is passed into the dynamicsjs animate function - third parameter - (see more at http://dynamicsjs.com/)animationSettings:{
}
}
,accept:{
// if true,then the settings.properties parameter will be distributed through the items in a non equal fashion// for instance,if we set settings.properties ={
translateX:100}
and we have options.visible = 4,// then the second item on the stack will translate 100px,the second one 75px and the third 50pxelastic:true,// object that is passed into the dynamicsjs animate function - second parameter - (see more at http://dynamicsjs.com/)animationProperties:{
}
,// object that is passed into the dynamicsjs animate function (see more at http://dynamicsjs.com/)animationSettings:{
}
}
}
*/
}
;
// set the initial styles for the visible itemsStack.prototype._init = function(){
// set default styles// first,the stackthis.el.style.WebkitPerspective = this.el.style.perspective = this.options.perspective + 'px';
this.el.style.WebkitPerspectiveOrigin = this.el.style.perspectiveOrigin = this.options.perspectiveOrigin;
var self = this;
// the itemsfor(var i = 0;
i < this.itemsTotal;
++i){
var item = this.items[i];
if( i < this.options.visible ){
item.style.opacity = 1;
item.style.pointerEvents = 'auto';
item.style.zIndex = i === 0 ? parseInt(this.options.visible + 1):parseInt(this.options.visible - i);
item.style.WebkitTransform = item.style.transform = 'translate3d(0px,0px,' + parseInt(-1 * 50 * i) + 'px)';
}
else{
item.style.WebkitTransform = item.style.transform = 'translate3d(0,0,-' + parseInt(this.options.visible * 50) + 'px)';
}
}
classie.add(this.items[this.current],'stack__item--current');
}
;
Stack.prototype.reject = function(callback){
this._next('reject',callback);
}
;
Stack.prototype.accept = function(callback){
this._next('accept',callback);
}
;
Stack.prototype.restart = function(){
this.hasEnded = false;
this._init();
}
;
Stack.prototype._next = function(action,callback){
if( this.isAnimating || ( !this.options.infinite && this.hasEnded ) ) return;
this.isAnimating = true;
// current itemvar currentItem = this.items[this.current];
classie.remove(currentItem,'stack__item--current');
// add animation classclassie.add(currentItem,action === 'accept' ? 'stack__item--accept':'stack__item--reject');
var self = this;
onEndAnimation(currentItem,function(){
// reset current itemcurrentItem.style.opacity = 0;
currentItem.style.pointerEvents = 'none';
currentItem.style.zIndex = -1;
currentItem.style.WebkitTransform = currentItem.style.transform = 'translate3d(0px,0px,-' + parseInt(self.options.visible * 50) + 'px)';
classie.remove(currentItem,action === 'accept' ? 'stack__item--accept':'stack__item--reject');
self.items[self.current].style.zIndex = self.options.visible + 1;
self.isAnimating = false;
if( callback ) callback();
if( !self.options.infinite && self.current === 0 ){
self.hasEnded = true;
// callbackself.options.onEndStack(self);
}
}
);
// set style for the other itemsfor(var i = 0;
i < this.itemsTotal;
++i){
if( i >= this.options.visible ) break;
if( !this.options.infinite ){
if( this.current + i >= this.itemsTotal - 1 ) break;
var pos = this.current + i + 1;
}
else{
var pos = this.current + i < this.itemsTotal - 1 ? this.current + i + 1:i - (this.itemsTotal - this.current - 1);
}
var item = this.items[pos],// stack items animationanimateStackItems = function(item,i){
item.style.pointerEvents = 'auto';
item.style.opacity = 1;
item.style.zIndex = parseInt(self.options.visible - i);
dynamics.animate(item,{
translateZ:parseInt(-1 * 50 * i)}
,self.options.stackItemsAnimation);
}
;
setTimeout(function(item,i){
return function(){
var preAnimation;
if( self.options.stackItemsPreAnimation ){
preAnimation = action === 'accept' ? self.options.stackItemsPreAnimation.accept:self.options.stackItemsPreAnimation.reject;
}
if( preAnimation ){
// items "pre animation" propertiesvar animProps ={
}
;
for (var key in preAnimation.animationProperties){
var interval = preAnimation.elastic ? preAnimation.animationProperties[key]/self.options.visible:0;
animProps[key] = preAnimation.animationProperties[key] - Number(i*interval);
}
// this one remains the same..animProps.translateZ = parseInt(-1 * 50 * (i+1));
preAnimation.animationSettings.complete = function(){
animateStackItems(item,i);
}
;
dynamics.animate(item,animProps,preAnimation.animationSettings);
}
else{
animateStackItems(item,i);
}
}
;
}
(item,i),this.options.stackItemsAnimationDelay);
}
// update currentthis.current = this.current < this.itemsTotal - 1 ? this.current + 1:0;
classie.add(this.items[this.current],'stack__item--current');
}
window.Stack = Stack;
}
)(window);
CSS代码(normalize.css):
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}
audio,canvas,video{display:inline-block;}
audio:not([controls]){display:none;height:0;}
[hidden]{display:none;}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}
body{margin:0;}
a:focus{outline:thin dotted;}
a:active,a:hover{outline:0;}
h1{font-size:2em;margin:0.67em 0;}
abbr[title]{border-bottom:1px dotted;}
b,strong{font-weight:bold;}
dfn{font-style:italic;}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}
mark{background:#ff0;color:#000;}
code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}
pre{white-space:pre-wrap;}
q{quotes:"\201C" "\201D" "\2018" "\2019";}
small{font-size:80%;}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
sup{top:-0.5em;}
sub{bottom:-0.25em;}
img{border:0;}
svg:not(:root){overflow:hidden;}
figure{margin:0;}
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}
legend{border:0;padding:0;}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}
button,input{line-height:normal;}
button,select{text-transform:none;}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}
button[disabled],html input[disabled]{cursor:default;}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
textarea{overflow:auto;vertical-align:top;}
table{border-collapse:collapse;border-spacing:0;}