Flipper Original
by alekskorovin
HTML
<script src="https://dl.dropboxusercontent.com/u/939178/master-class-chikuyonok/pointerEvents.js"></script>
<script src="https://dl.dropboxusercontent.com/u/939178/master-class-chikuyonok/tween.js"></script>
<div class="wrap">
<div class="card card_cur" style="background: red;">1</div>
<div class="card" style="background: blue;">2</div>
<div class="card" style="background: green;">3</div>
<div class="card" style="background: yellow;">4</div>
</div>
CSS
html, body {
padding: 0;
margin: 0;
width: 100%;
}
.wrap {
position: relative;
margin: 0 auto;
width: 320px;
}
.card {
position: absolute;
width: 320px;
height: 480px;
font-size: 260px;
font-family: sans-serif;
overflow: hidden;
line-height: 480px;
text-align: center;
}
.card_cur {
z-index: 2;
}
.flipper {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1004;
-webkit-user-select: none;
user-select: none;
-webkit-transform-style: preserve-3d;
-webkit-perspective: 1000px;
}
.flipper__item {
position: absolute;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* Сразу выносим слой на GPU */
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
/**
* Обозначения элементов:
* .flipper__item_current — текущий (активный) слой
* .flipper__item_next – следующий слой
* .flipper__item_h1 — верхняя половина слоя
* .flipper__item_h2 — нижняя половина слоя
*/
.flipper__item_current.flipper__item_h1 {
z-index: 1 !important;
}
.flipper__item_current.flipper__item_h2 {
z-index: 3 !important;
}
.flipper__item_next.flipper__item_h1 {
z-index: 4 !important;
-webkit-transform: rotateX(-180deg);
-moz-transform: rotateX(-180deg);
-ms-transform: rotateX(-180deg);
-o-transform: rotateX(-180deg);
transform: rotateX(-180deg);
}
.flipper__item_next.flipper__item_h2 {
z-index: 2 !important;
}
.flipper__shade {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
opacity: 0;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.flipper__shade_light {
background: rgba(255, 255, 255, 0.5);
}
.flipper__shade_dark {
background: rgba(0, 0, 0, 0.9);
}
JavaScript
(function() {
/**
* Объект, описывающий текущее состояние переворота.
* Если равен null, значит, ничего сейчас не переворачиваем
* @type {Object}
*/
var flipState = null;
/**
* Флаг, указывающий, заблокировано ли взаимодействие
* с картами (например, во время анимации)
* @type {Boolean}
*/
var locked = false;
/**
* Всопомгательная функция, которая создаёт элемент с указанным
* именем и классами
* @param {String} name Название элемента
* @param {String} className Классы элемента
* @return {Element}
*/
function el(name, className) {
var elem = document.createElement(name);
if (className) {
elem.className = className;
}
return elem;
}
/**
* Проверяет, сработало ли событие на нужном элементе
* @param {Event} evt
* @return {Boolean}
*/
function hitTest(evt) {
var elem = evt.target;
while (elem && elem !== document) {
if (elem.classList.contains('card')) {
return true;
}
elem = elem.parentNode;
}
}
/**
* Вспомогательный метод, который возвращает
* массив карт, а также индекс текущей карты
* @return {Object}
*/
function getCards() {
var cards = document.querySelectorAll('.card');
var out = {
list: [],
selected: -1
};
for (var i = 0, il = cards.length; i < il; i++) {
out.list.push(cards[i]);
if (cards[i].classList.contains('card_cur')) {
out.selected = i;
}
}
return out;
}
/**
* Возвращает объект с картами, котороые нужно перевернуть
* Свойства объекта:
* - cur: текущая карта
* - next: следующая карта
* @return {Object}
*/
function getCardsToFlip() {
var cards = getCards();
return {
cur: cards.list[cards.selected],
next: cards.list[cards.selected + 1]
};
}
/**
* Берёт следующую карту (относительно текущей)
* и помечает её как активную
*/
function pickNextCard() {
var cards = getCards();
var cur = cards.list[cards.selected];
if (cur) {
cur.classList.remove('card_cur');
}
var next =...