JSFiddle - React, Tailwind, and code Playground
by Keith Chu
HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Pull to Open - Interaction Test</title>
<link rel="stylesheet" href="stylesheets/style2.css" />
</head>
<body>
<div class="card">
<div class="card-inner">
<h1>Totoro</h1>
<img src="http://f.cl.ly/items/3N131r1b1N3f40440e2Y/totoro.jpg" />
<p>$15</p>
</div>
<div class="card-outer">
<div class="card-outer-top"></div>
<div class="card-pulltab">
<i class="card-cut"></i>
<a href="#">Slice to Open</a>
</div>
<div class="card-outer-bottom"></div>
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="scripts/scripts2.min.js"></script>
</body>
</html>
CSS
/* line 1, ../sass/style2.sass */
body {
background-image: url("http://f.cl.ly/items/400m0O0c2F0n1D421U1Q/noise-7b209cf74b1a68ced00edf9fe5bba036.gif");
color: #454545;
font: 30px sans-serif;
font-weight: 100;
padding: 100px; }
/* line 8, ../sass/style2.sass */
.card {
border-radius: 5px;
box-shadow: inset 0 0 3px 1px rgba(0, 0, 0, 0.5), inset 0 0 3px 4px rgba(255, 255, 255, 0.2), inset 2px 2px 2px 2px rgba(255, 255, 255, 0.5), 2px 4px 4px 1px rgba(0, 0, 0, 0.05), 1px 1px 10px rgba(0, 0, 0, 0.3);
height: 547px;
position: relative;
width: 547px;
-webkit-perspective: 900; }
/* line 16, ../sass/style2.sass */
.card.slicing .card-cut {
margin-top: -3px;
width: 100%; }
/* line 19, ../sass/style2.sass */
.card.slicing .card-pulltab {
border-color: transparent;
-webkit-animation: falloff 3s ease;
-webkit-animation-fill-mode: forwards;
z-index: 4; }
/* line 24, ../sass/style2.sass */
.card.slicing .card-pulltab:before, .card.slicing .card-pulltab:after {
display: none; }
/* line 26, ../sass/style2.sass */
.card.slicing .card-outer-top {
border-bottom: 2px solid rgba(0, 0, 0, 0.35);
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.3);
-webkit-animation: card-open-top 1.5s ease 3s;
-webkit-animation-fill-mode: forwards; }
/* line 31, ../sass/style2.sass */
.card.slicing .card-outer-bottom {
border-top: 1px solid rgba(0, 0, 0, 0.25);
box-shadow: 0 -5px 5px rgba(0, 0, 0, 0.3);
-webkit-animation: card-open-bottom 1.5s ease 3s;
-webkit-animation-fill-mode: forwards;
-webkit-transition: falloff-outer-bottom 3s ease; }
/* line 37, ../sass/style2.sass */
.card-inner {
background: url("http://f.cl.ly/items/3i30303K260v3Q332a2T/50-50-5-monochrome.png"), -webkit-linear-gradient(-90deg, white, rgba(255, 255, 255, 0.5));
border-radius: 5px;
box-shadow: inset 0 0 3px 1px rgba(0, 0, 0, 0.5), inset 0 0 3px 4px rgba(255, 255, 255, 0.2), inset 2px 2px 2px 2px rgba(255, 255, 255,...
JavaScript
var touchSupport = ('ontouchstart' in document.documentElement);
var actionStart = (touchSupport) ? 'touchstart' : 'mousedown',
actionMove = (touchSupport) ? 'touchmove' : 'mousemove',
actionEnd = (touchSupport) ? 'touchend touchcancel' : 'mouseup';
var touch = {},
dx = 0, dy = 0,
cutWidth = 0,
cardLeftEdge = $(".card").offset().left,
cardWidth = 540,
swiping = false,
swipeTolerance = 50;
$('body').on(actionStart, function(e){
e = e.originalEvent;
e.preventDefault();
if (touchSupport) {
if (e.touches.length === 1) {
touch.x1 = e.touches[0].pageX;
touch.y1 = e.touches[0].pageY;
}
} else {
touch.x1 = e.pageX;
touch.y1 = e.pageY;
}
// bind after touchstart/mousedown, so event doesn't fire haphazardly
$(this).on(actionMove, function(e){
e = e.originalEvent;
e.preventDefault();
if (touchSupport) {
if (e.touches.length === 1) {
dx = e.touches[0].pageX - touch.x1;
dy = e.touches[0].pageY - touch.y1;
if (Math.abs(dx) > 0 && Math.abs(dy) < 6 && !swiping) {
swiping = true;
}
}
} else {
dx = e.pageX - touch.x1;
dy = e.pageY - touch.y1;
if (Math.abs(dx) > 0 && Math.abs(dy) < 6 && !swiping) {
swiping = true;
}
}
// a swipe motion initiated
if (swiping) {
// left-to-right swipe
if (touch.x1 < (cardLeftEdge + swipeTolerance)) {
cutWidth = Math.min(((e.pageX - cardLeftEdge) / cardWidth) * 100, 100);
$(".card-cut").css("width", cutWidth + "%");
if (e.pageX > (cardWidth + cardLeftEdge - swipeTolerance)) {
$(".card").addClass("slicing");
}
}
// right-to-left swipe
else if (touch.x1 > (cardWidth + cardLeftEdge - swipeTolerance)) {
cutWidth = Math.min((((cardWidth + cardLeftEdge) - e.pageX) / cardWidth) * 100, 100);
$(".card-cut").addClass("reverse").css("width", cutWidth + "%");
if (e.pageX...