我正在尝试制作记忆游戏,并且在点击它们时我很难让卡片翻转。我期望以下for循环在单击一个卡(对应于具有类displayCard
的每个li
项)时调用函数card
,该函数切换类show
和open
(将卡片设置为可见[显示图标]并更改背景颜色)。有什么建议?
For loop:
for (let i = 0; i < cards.length; i++) {
card = cards[i];
card.addEventListener('click', displayCard);
card.addEventListener('click', cardOpen);
card.addEventListener('click', congratulations);
}
displayCard
功能:
let displayCard = function() {
this.classList.toggle('open');
this.classList.toggle('show');
this.classList.toggle('disabled');
};
课程show
和open
的CSS:
.card-deck .card.open {
/* transform: rotateY(0); */
background: #02b3e4;
cursor: default;
animation-name: flipInY;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.show {
font-size: 33px;
}
.show {
visibility: visible !important;
opacity: 100 !important;
}
答案 0 :(得分:2)
您的代码中有两个错误需要修复,然后发生翻转:
startGame
函数中,deck.appendChild
不是函数。 deck使用document.getElementsByClassName(&#39; card-deck&#39;)初始化。 document.getElementsByClassName返回一个数组。您需要选择此数组的第一个索引。
{li>在startGame
函数中,interval
未定义。在声明interval
变量之前调用您的函数。向上移动interval
变量声明,使用var
关键字将其声明为&#34;保留&#34;标识符。
let card = document.getElementsByClassName('card');
// Spread operator (new in ES6) allows iterable to expand where 0+ arguments are expected
let cards = [...card];
let deck = document.getElementsByClassName('card-deck')[0];
let moves = 0;
let counter = document.querySelector('.moves');
let stars = document.querySelectorAll('.fa-star');
let matchingCard = document.getElementsByClassName('matching');
let starsList = document.querySelectorAll('.stars li');
let closeIcon = document.querySelector('.close');
let modal = document.getElementsByClassName('main-modal');
let openedCards = [];
// Game timer
let second = 0, minute = 0, hour = 0;
let timer = document.querySelector('.timer');
let interval;
// Shuffle function from http://stackoverflow.com/a/2450976
function shuffle(array) {
let currentIndex = array.length, temporaryValue, randomIndex;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// Shuffles cards upon page load
document.body.onload = startGame();
function startGame() {
// Shuffles deck
cards = shuffle(cards);
// Removes any existing classes from each card
for (let i = 0; i < cards.length; i++) {
deck.innerHTML = '';
[].forEach.call(cards, function(item) {
deck.appendChild(item);
});
cards[i].classList.remove('show', 'open', 'matching', 'disabled');
}
// Resets number of moves
moves = 0;
counter.innerHTML = moves;
// Resets star rating
for (let i = 0; i < stars.length; i++) {
stars[i].style.color = '#ffd700';
stars[i].style.visibility = 'visible';
}
// Resets timer
let second = 0;
let minute = 0;
let hour = 0;
let timer = document.querySelector('.timer');
timer.innerHTML = '0 mins 0 secs';
if (typeof interval != "undefined") {
sclearInterval(interval);
}
}
// Toggles open and show classes to display cards
let displayCard = function() {
this.classList.toggle('open');
this.classList.toggle('show');
this.classList.toggle('disabled');
};
// Adds opened cards to openedCards list and checks if cards are a match or not
function cardOpen() {
openedCards.push(this);
let len = openedCards.length;
if (len === 2) {
moveCounter();
if (openedCards[0].type === openedCards[1].type) {
matching();
} else {
notMatching();
}
}
}
// When cards match
function matching() {
openedCards[0].classList.add('matching', 'disabled');
openedCards[1].classList.add('matching', 'disabled');
openedCards[0].classList.remove('show', 'open');
openedCards[1].classList.remove('show', 'open');
openedCards = [];
}
// When cards don't match
function notMatching() {
openedCards[0].classList.add('not-matching');
openedCards[1].classList.add('not-matching');
disable();
setTimeout(function() {
openedCards[0].classList.remove('show', 'open', 'not-matching');
openedCards[1].classList.remove('show', 'open', 'not-matching');
enable();
openedCards = [];
}, 1100);
}
// Disables cards temporarily
function disable() {
Array.prototype.filter.call(cards, function(card) {
card.classList.add('disabled');
});
}
// Enables cards, disables matching cards
function enable() {
Array.prototype.filter.call(cards, function(card) {
card.classList.remove('disabled');
for (let i = 0; i < matchingCard.length; i++) {
matchingCard[i].classList.add('disabled');
}
});
}
// Counts player's moves
function moveCounter() {
moves++;
counter.innerHTML = moves;
// Starts timer on first click
if (moves == 1) {
second = 0;
minute = 0;
hour = 0;
startTimer();
}
// Sets star rating based on number of moves
if (moves > 8 && moves < 12) {
for (i = 0; i < 3; i++) {
if (i > 1) {
stars[i].style.visibility = 'collapse';
}
}
}
else if (moves > 13) {
for (i = 0; i < 3; i++) {
if (i > 0) {
stars[i].style.visibility = 'collapse';
}
}
}
}
function startTimer() {
interval = setInterval(function() {
timer.innerHTML = minute + 'mins ' + second + 'secs';
second++;
if (second == 60) {
minute++;
second = 0;
}
if (minute == 60) {
hour++;
minute = 0;
}
}, 1000);
}
// Congratulates player when all cards match and shows modal, moves, time and rating
function congratulations() {
if (matchingCard.length == 16) {
clearInterval(interval);
let finalTime = timer.innerHTML;
// Shows congratulations modal
modal.classList.add('show');
let starRating = document.querySelector('.stars').innerHTML;
// Shows move, time, and rating on modal
document.getElementsByClassName('final-move').innerHTML = moves;
document.getElementsByClassName('star-rating').innerHTML = starRating;
document.getElementsByClassName('total-time').innerHTML = finalTime;
closeModal();
}
}
// Closes modal upon clicking its close icon
function closeModal() {
closeIcon.addEventListener('click', function(e) {
modal.classList.remove('show');
startGame();
});
}
function reset() {
modal.classList.remove('show');
startGame();
}
// Adds event listeners to each card
for (let i = 0; i < cards.length; i++) {
card = cards[i];
card.addEventListener('click', displayCard);
card.addEventListener('click', cardOpen);
card.addEventListener('click', congratulations);
}
&#13;
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #ffffff;
font-family: 'Permanent Marker', cursive;
font-size: 16px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
h1 {
font-family: 'Gloria Hallelujah', cursive;
}
/* DECK OF CARDS */
.card-deck {
width: 85%;
background: #716F71;
padding: 1rem;
border-radius: 4px;
box-shadow: 8px 9px 26px 0 rgba(46, 61, 73, 0.5);
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
margin: 0 0 3em;
}
.card-deck .card {
height: 3.7rem;
width: 3.7rem;
margin: 0.2rem 0.2rem;
background: #141214;;
font-size: 0;
color: #ffffff;
border-radius: 5px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 5px 2px 20px 0 rgba(46, 61, 73, 0.5);
}
.card-deck .card.open {
/* transform: rotateY(0); */
background: #02b3e4;
cursor: default;
animation-name: flipInY;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.show {
font-size: 33px;
}
.show {
visibility: visible !important;
opacity: 100 !important;
}
.card-deck .card.matching {
cursor: default;
background: #E5F720;
font-size: 33px;
animation-name: rubberBand;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.not-matching {
animation-name: pulse;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
background: #e2043b;
}
.card-deck .card.disabled {
pointer-events: none;
opacity: 0.9;
}
/* SCORE PANEL */
.score-panel {
text-align: left;
margin-bottom: 10px;
}
.score-panel .stars {
margin: 0;
padding: 0;
display: inline-block;
margin: 0 5px 0 0;
}
.score-panel .stars li {
list-style: none;
display: inline-block;
}
.score-panel .restart {
float: right;
cursor: pointer;
}
.fa-star {
color: #FFD700;
}
.timer {
display: inline-block;
margin: 0 1rem;
}
/* CONGRATULATIONS MODAL */
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
margin: 70px auto;
padding: 20px;
background: #ffffff;
border-radius: 5px;
width: 85%;
position: relative;
transition: all 5s ease-in-out;
font-family: 'Gloria Hallelujah', cursive;
}
.popup h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup .close:hover {
color: #e5f720;
}
.popup .congrats-message,
.info-message {
max-height: 30%;
overflow: auto;
text-align: center;
}
.star-rating li {
display: inline-block;
}
.play-again {
background-color: #141214;
padding: 0.7rem 1rem;
font-size: 1.1rem;
display: block;
margin: 0 auto;
width: 50%;
font-family: 'Gloria Hallelujah', cursive;
color: #ffffff;
border-radius: 5px;
}
/* Animations */
@keyframes flipInY {
from {
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
animation-timing-function: ease-in;
opacity: 0;
}
40% {
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
animation-timing-function: ease-in;
}
60% {
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
opacity: 1;
}
80% {
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
to {
transform: perspective(400px);
}
}
@keyframes rubberBand {
from {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1);
}
40% {
transform: scale3d(0.75, 1.25, 1);
}
50% {
transform: scale3d(1.15, 0.85, 1);
}
65% {
transform: scale3d(.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, .95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
@keyframes pulse {
from {
transform: scale3d(1, 1, 1);
}
50% {
transform: scale3d(1.2, 1.2, 1.2);
}
to {
transform: scale3d(1, 1, 1);
}
}
/* MEDIA QUERIES */
@media (max-width: 320px) {
.card-deck {
width: 85%;
}
.card-deck .card {
height: 4.7rem;
width: 4.7rem;
}
}
/* For tablets and larger screens */
@media (min-width: 768px) {
.container {
font-size: 22px;
}
.card-deck {
width: 660px;
height: 680px;
}
.card-deck .card {
height: 125px;
width: 125px;
}
.popup {
width: 60%;
}
}
&#13;
<!-- <!doctype html> -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Matching Game</title>
<meta name="description" content="">
<link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Coda">
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<header>
<h1>Matching Game</h1>
</header>
<section class="score-panel">
<ul class="stars">
<li><i class="fa fa-star"></i></li>
<li><i class="fa fa-star"></i></li>
<li><i class="fa fa-star"></i></li>
</ul>
<span class="moves">0</span> moves
<div class="timer"></div>
<div class="restart" onclick=startGame()>
<i class="fa fa-repeat"></i>
</div>
</section>
<ul class="card-deck">
<li class="card" type="diamond">
<i class="fa fa-diamond"></i>
</li>
<li class="card" type="plane">
<i class="fa fa-paper-plane-o"></i>
</li>
<li class="card matching" type="anchor">
<i class="fa fa-anchor"></i>
</li>
<li class="card" type="bolt" >
<i class="fa fa-bolt"></i>
</li>
<li class="card" type="cube">
<i class="fa fa-cube"></i>
</li>
<li class="card matching" type="anchor">
<i class="fa fa-anchor"></i>
</li>
<li class="card" type="leaf">
<i class="fa fa-leaf"></i>
</li>
<li class="card" type="bicycle">
<i class="fa fa-bicycle"></i>
</li>
<li class="card" type="diamond">
<i class="fa fa-diamond"></i>
</li>
<li class="card" type="bomb">
<i class="fa fa-bomb"></i>
</li>
<li class="card" type="leaf">
<i class="fa fa-leaf"></i>
</li>
<li class="card" type="bomb">
<i class="fa fa-bomb"></i>
</li>
<li class="card open show" type="bolt">
<i class="fa fa-bolt"></i>
</li>
<li class="card" type="bicycle">
<i class="fa fa-bicycle"></i>
</li>
<li class="card" type="plane">
<i class="fa fa-paper-plane-o"></i>
</li>
<li class="card" type="cube">
<i class="fa fa-cube"></i>
</li>
</ul>
<div class="main-modal overlay">
<div class="popup">
<h2>Congratulations!</h2>
<a class="close" href=# >×</a>
<div class="congrats-message">
Congratulations, you're a winner!
</div>
<div class="info-message">
<p>You made <span class=final-move></span> moves </p>
<p>In <span class=total-time></span></p>
<p>Rating: <span class=star-rating></span></p>
</div>
<button class="play-again" onclick="reset()">
Play again
</button>
</div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
&#13;