티스토리 뷰
HTML
<div class="wrap__card">
<div class="card__inner">
<ul class="cards">
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-1.png" alt="이미지1">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-1.png" alt="이미지1">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-2.png" alt="이미지2">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-2.png" alt="이미지2">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-3.png" alt="이미지3">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-3.png" alt="이미지3">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-4.png" alt="이미지4">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-4.png" alt="이미지4">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-5.png" alt="이미지5">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-5.png" alt="이미지5">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-9.png" alt="이미지6">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-9.png" alt="이미지6">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-7.png" alt="이미지7">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-7.png" alt="이미지7">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-8.png" alt="이미지8">
</div>
</li>
<li>
<div class="view front">
<img src="img/img-6.png" alt="앞면">
</div>
<div class="view back">
<img src="img/img-8.png" alt="이미지8">
</div>
</li>
</ul>
</div>
</div>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul{
list-style: none;
}
img {
width: 100%;
vertical-align: top;
}
body {
background: #007bff;
}
.wrap__card {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.card__inner {
width: 700px;
height: 700px;
background-color: #fff;
border-radius: 20px;
padding: 30px;
}
.cards {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-content: space-around;
width: 100%;
height: 100%;
}
.cards li {
width: calc(100%/4 - 20px);
height: calc(100%/4 - 20px);
/* background: #ccc; */
/* border: 1px solid #ccc; */
perspective: 1000px;
transform-style: preserve-3d;
position: relative;
}
.cards li .view {
position: absolute;
background:#F7BDD6;
padding: 10%;
transition: transform 0.25s linear;
backface-visibility: hidden;
width: 100%;
height: 100%;
/* 이벤트 버블링 효과 방지 */
user-select: none;
pointer-events: none;
}
.cards li .view.front {
z-index: 10;
transform: rotateY(0deg);
}
.cards li .view.back {
transform: rotateY(-180deg);
}
.cards li.flip .view.front {
transform: rotateY(180deg);
}
.cards li.flip .view.back {
transform: rotateY(0deg);
}
.cards li.shake {
animation: shake 0.35s ease-in-out;
}
@keyframes shake {
0% {transform: translateX(0);}
20% {transform: translateX(-13px);}
40% {transform: translateX(13px);}
60% {transform: translateX(-8px);}
80% {transform: translateX(8px);}
100% {transform: translateX(0);}
}
SCRIPT
//01. HTML/CSS 디자인 구성
//02. 클릭한 카드 뒤집기
//03. 두개의 카드 뒤집기 확인하기(첫번째, 두번째)
//04. 클릭한 카드의 두개의 이미지 가져오기
//05. 두개의 이미지 비교하기
//06. 틀린 이미지 애니메이션 효과 주기
//07. 빨리 클릭하면 버그 발생 처리하기
const cards = document.querySelectorAll(".cards li");
let cardOne, cardTwo;
let disableDeck = false;
function flipCard(e) {
let clickedCard = e.target;
if(clickedCard !== cardOne && !disableDeck) {
clickedCard.classList.add("flip");
if(!cardOne){
return cardOne = clickedCard;
}
cardTwo = clickedCard;
disableDeck = true;
let cardOneImg = cardOne.querySelector(".back img").src;
let cardTwoImg = cardTwo.querySelector(".back img").src;
matchCards(cardOneImg, cardTwoImg);
}
}
//05. 두개의 이미지 비교하기
function matchCards(img1, img2){
if(img1==img2){
cardOne.removeEventListener("click",flipCard);
cardTwo.removeEventListener("click",flipCard);
cardOne = cardTwo = "";
disableDeck = false;
} else {
setTimeout(()=>{
cardOne.classList.add("shake");
cardTwo.classList.add("shake");
},400)
setTimeout(()=>{
cardOne.classList.remove("shake","flip");
cardTwo.classList.remove("shake","flip");
cardOne = cardTwo = "";
disableDeck = false;
},1200)
}
}
cards.forEach(card => {
card.addEventListener("click", flipCard)
})
댓글
© 2018 webstoryboy