Tinder swipe cards made with hammer.js.
A Pen by Rob Vermeer on CodePen.
<div class="tinder"> | |
<div class="tinder--status"> | |
<i class="fa fa-remove"></i> | |
<i class="fa fa-heart"></i> | |
</div> | |
<div class="tinder--cards"> | |
<div class="tinder--card"> | |
<img src="https://placeimg.com/600/300/people"> | |
<h3>Demo card 1</h3> | |
<p>This is a demo for Tinder like swipe cards</p> | |
</div> | |
<div class="tinder--card"> | |
<img src="https://placeimg.com/600/300/animals"> | |
<h3>Demo card 2</h3> | |
<p>This is a demo for Tinder like swipe cards</p> | |
</div> | |
<div class="tinder--card"> | |
<img src="https://placeimg.com/600/300/nature"> | |
<h3>Demo card 3</h3> | |
<p>This is a demo for Tinder like swipe cards</p> | |
</div> | |
<div class="tinder--card"> | |
<img src="https://placeimg.com/600/300/tech"> | |
<h3>Demo card 4</h3> | |
<p>This is a demo for Tinder like swipe cards</p> | |
</div> | |
<div class="tinder--card"> | |
<img src="https://placeimg.com/600/300/arch"> | |
<h3>Demo card 5</h3> | |
<p>This is a demo for Tinder like swipe cards</p> | |
</div> | |
</div> | |
<div class="tinder--buttons"> | |
<button id="nope"><i class="fa fa-remove"></i></button> | |
<button id="love"><i class="fa fa-heart"></i></button> | |
</div> | |
</div> |
'use strict'; | |
var tinderContainer = document.querySelector('.tinder'); | |
var allCards = document.querySelectorAll('.tinder--card'); | |
var nope = document.getElementById('nope'); | |
var love = document.getElementById('love'); | |
function initCards(card, index) { | |
var newCards = document.querySelectorAll('.tinder--card:not(.removed)'); | |
newCards.forEach(function (card, index) { | |
card.style.zIndex = allCards.length - index; | |
card.style.transform = 'scale(' + (20 - index) / 20 + ') translateY(-' + 30 * index + 'px)'; | |
card.style.opacity = (10 - index) / 10; | |
}); | |
tinderContainer.classList.add('loaded'); | |
} | |
initCards(); | |
allCards.forEach(function (el) { | |
var hammertime = new Hammer(el); | |
hammertime.on('pan', function (event) { | |
el.classList.add('moving'); | |
}); | |
hammertime.on('pan', function (event) { | |
if (event.deltaX === 0) return; | |
if (event.center.x === 0 && event.center.y === 0) return; | |
tinderContainer.classList.toggle('tinder_love', event.deltaX > 0); | |
tinderContainer.classList.toggle('tinder_nope', event.deltaX < 0); | |
var xMulti = event.deltaX * 0.03; | |
var yMulti = event.deltaY / 80; | |
var rotate = xMulti * yMulti; | |
event.target.style.transform = 'translate(' + event.deltaX + 'px, ' + event.deltaY + 'px) rotate(' + rotate + 'deg)'; | |
}); | |
hammertime.on('panend', function (event) { | |
el.classList.remove('moving'); | |
tinderContainer.classList.remove('tinder_love'); | |
tinderContainer.classList.remove('tinder_nope'); | |
var moveOutWidth = document.body.clientWidth; | |
var keep = Math.abs(event.deltaX) < 80 || Math.abs(event.velocityX) < 0.5; | |
event.target.classList.toggle('removed', !keep); | |
if (keep) { | |
event.target.style.transform = ''; | |
} else { | |
var endX = Math.max(Math.abs(event.velocityX) * moveOutWidth, moveOutWidth); | |
var toX = event.deltaX > 0 ? endX : -endX; | |
var endY = Math.abs(event.velocityY) * moveOutWidth; | |
var toY = event.deltaY > 0 ? endY : -endY; | |
var xMulti = event.deltaX * 0.03; | |
var yMulti = event.deltaY / 80; | |
var rotate = xMulti * yMulti; | |
event.target.style.transform = 'translate(' + toX + 'px, ' + (toY + event.deltaY) + 'px) rotate(' + rotate + 'deg)'; | |
initCards(); | |
} | |
}); | |
}); | |
function createButtonListener(love) { | |
return function (event) { | |
var cards = document.querySelectorAll('.tinder--card:not(.removed)'); | |
var moveOutWidth = document.body.clientWidth * 1.5; | |
if (!cards.length) return false; | |
var card = cards[0]; | |
card.classList.add('removed'); | |
if (love) { | |
card.style.transform = 'translate(' + moveOutWidth + 'px, -100px) rotate(-30deg)'; | |
} else { | |
card.style.transform = 'translate(-' + moveOutWidth + 'px, -100px) rotate(30deg)'; | |
} | |
initCards(); | |
event.preventDefault(); | |
}; | |
} | |
var nopeListener = createButtonListener(false); | |
var loveListener = createButtonListener(true); | |
nope.addEventListener('click', nopeListener); | |
love.addEventListener('click', loveListener); |
<script src="https://hammerjs.github.io/dist/hammer.min.js"></script> |
*, *:before, *:after { | |
box-sizing: border-box; | |
padding: 0; | |
margin: 0; | |
} | |
body { | |
background: #CCFBFE; | |
overflow: hidden; | |
font-family: sans-serif; | |
} | |
.tinder { | |
width: 100vw; | |
height: 100vh; | |
overflow: hidden; | |
display: flex; | |
flex-direction: column; | |
position: relative; | |
opacity: 0; | |
transition: opacity 0.1s ease-in-out; | |
} | |
.loaded.tinder { | |
opacity: 1; | |
} | |
.tinder--status { | |
position: absolute; | |
top: 50%; | |
margin-top: -30px; | |
z-index: 2; | |
width: 100%; | |
text-align: center; | |
pointer-events: none; | |
} | |
.tinder--status i { | |
font-size: 100px; | |
opacity: 0; | |
transform: scale(0.3); | |
transition: all 0.2s ease-in-out; | |
position: absolute; | |
width: 100px; | |
margin-left: -50px; | |
} | |
.tinder_love .fa-heart { | |
opacity: 0.7; | |
transform: scale(1); | |
} | |
.tinder_nope .fa-remove { | |
opacity: 0.7; | |
transform: scale(1); | |
} | |
.tinder--cards { | |
flex-grow: 1; | |
padding-top: 40px; | |
text-align: center; | |
display: flex; | |
justify-content: center; | |
align-items: flex-end; | |
z-index: 1; | |
} | |
.tinder--card { | |
display: inline-block; | |
width: 90vw; | |
max-width: 400px; | |
height: 70vh; | |
background: #FFFFFF; | |
padding-bottom: 40px; | |
border-radius: 8px; | |
overflow: hidden; | |
position: absolute; | |
will-change: transform; | |
transition: all 0.3s ease-in-out; | |
cursor: -webkit-grab; | |
cursor: -moz-grab; | |
cursor: grab; | |
} | |
.moving.tinder--card { | |
transition: none; | |
cursor: -webkit-grabbing; | |
cursor: -moz-grabbing; | |
cursor: grabbing; | |
} | |
.tinder--card img { | |
max-width: 100%; | |
pointer-events: none; | |
} | |
.tinder--card h3 { | |
margin-top: 32px; | |
font-size: 32px; | |
padding: 0 16px; | |
pointer-events: none; | |
} | |
.tinder--card p { | |
margin-top: 24px; | |
font-size: 20px; | |
padding: 0 16px; | |
pointer-events: none; | |
} | |
.tinder--buttons { | |
flex: 0 0 100px; | |
text-align: center; | |
padding-top: 20px; | |
} | |
.tinder--buttons button { | |
border-radius: 50%; | |
line-height: 60px; | |
width: 60px; | |
border: 0; | |
background: #FFFFFF; | |
display: inline-block; | |
margin: 0 8px; | |
} | |
.tinder--buttons button:focus { | |
outline: 0; | |
} | |
.tinder--buttons i { | |
font-size: 32px; | |
vertical-align: middle; | |
} | |
.fa-heart { | |
color: #FFACE4; | |
} | |
.fa-remove { | |
color: #CDD6DD; | |
} |
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" /> |
Tinder swipe cards made with hammer.js.
A Pen by Rob Vermeer on CodePen.