728x90
반응형
searchEffect07
2분 동안 CSS 속성 검색하기
HTML
검색을 진행하는 동안에 진행 될 음악, 진행 시에 사용되는 타이머 등의 필요한 구조를 구성합니다.
코드보기
<main id="main">
<div class="search__wrap">
<div class="search__audio">
<span>
<span class="play">
</span>
<span class="stop">
</span>
</span>
<audio id="audio" src="../assets/audio/music_audio08.mp3" loop="loop"></audio>
<!--loop="loop" : 계속 반복되게 해줌-->
<audio id="correctAudio" src="../assets/audio/searchCorrect-.mp3"></audio>
<audio id="incorrectAudio" src=""></audio>
</div>
<span>CSS 속성 검색 이벤트</span>
<h1><a href="searchEffect.html">2분 동안 CSS 속성 검색하기</a></h1>
<p class="desc">
2분 동안 CSS 속성을 많이 검색하면 점수가 올라갑니다.<br>
힌트보기는 한번 이용할 수 있습니다.
</p>
<div class="time">
<span>2:00</span>
</div>
<div class="search__box">
<label for="search">검색하기</label>
<input type="text" id="search" placeholder="CSS 속성을 입력해주세요!">
<div class="start">버튼을 누르면 게임이 시작됩니다.</div>
</div>
<div class="search__info center">
<div>전체 속성 갯수 : <span class="num">0</span></div>
<div>현재 맞춘 갯수 : <span class="answer__num">0</span></div>
</div>
<div class="search__answers">
</div>
<div class="search__missAnswers">
</div>
<div class="search__list">
</div>
<div class="search__result">
<div class="svg__wrap">
<div class="result"></div>
<button class="restart">다시 도전하기</button>
</div>
<div class="restart"></div>
</div>
</div>
</main>
CSS
css 구조를 구성합니다
코드보기
#header {
display: flex;
justify-content: space-between;
}
#header nav {
margin: 10px;
}
#header nav li {
position: relative;
display: inline;
}
#header nav li a {
width: 30px;
height: 30px;
border: 1px solid var(--htmlColor);
border-radius: 50%;
display: inline-block;
text-align: center;
line-height: 30px;
font-family: "NexonLv1Gothic";
}
#header nav li.active a {
background-color: var(--htmlColor);
color: #fff;
}
#header nav li .sub {
position: absolute;
left: 0;
top: 35px;
width: 400px;
}
#header nav li .sub li a {
width: auto;
background-color: transparent;
color: var(--htmlColor);
border: 0;
text-align: left;
line-height: 1.2;
}
#header nav li .sub li.active a {
text-decoration: underline;
}
/* main */
#main {
margin: 50px 10px;
}
.search__wrap {
max-width: 1400px;
margin: 0 auto;
border: 3px solid var(--htmlColor);
border-radius: 20px;
background-color: #f1f3f6;
padding: 30px;
text-align: center;
}
.search__wrap > span {
font-size: 20px;
margin-bottom: 20px;
display: inline-block;
}
.search__wrap > h1 a {
font-family: "Tmon";
color: var(--htmlColor);
font-size: 5vw;
margin-bottom: 10px;
}
.search__wrap .desc {
line-height: 1.4;
padding: 20px 0;
}
.search__wrap .time {
width: 140px;
height: 140px;
line-height: 140px;
text-align: center;
border-radius: 50%;
margin: 0 auto;
background: var(--htmlColor);
}
.search__wrap .time span {
color: #fff;
font-size: 34px;
font-weight: 100;
}
.search__box {
margin-bottom: 20px;
position: relative;
}
.search__box label {
position: absolute;
clip: rect(0 0 0 0);
width: 1px;
height: 1px;
margin: -1px;
overflow: hidden;
}
.search__box input {
border: 2px solid var(--htmlColor);
padding: 15px 40px;
width: 30%;
border-radius: 50px;
font-size: 20px;
margin-top: 20px;
}
.search__box .start {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
background: #223547;
width: 30%;
border-radius: 50px;
font-size: 20px;
border: 2px solid var(--htmlColor);
padding: 15px 40px;
color: #fff;
cursor: pointer;
}
.search__list li {
text-align: left;
line-height: 1.7;
}
.search__list li.show {
display: block;
}
.search__list li.hide {
display: none;
}
.search__list span {
display: inline-block;
padding: 10px 20px;
border: 1px solid var(--htmlColor);
border-radius: 50px;
margin: 5px;
transition: all 0.3s;
cursor: pointer;
}
.search__list span:hover {
background-color: var(--htmlColor);
color: #fff;
}
.search__list em {
float: right;
font-style: normal;
}
.search__list .line {
margin: 50px 0;
}
.search__list .line li {
background: #e3eaf5;
padding: 10px 30px;
margin-bottom: 5px;
border-radius: 50px;
}
.search__list .line li:hover {
background: #d3e2fa;
cursor: pointer;
}
.search__info {
text-align: right;
margin-bottom: 30px;
padding-bottom: 10px;
border-bottom: 2px dashed var(--htmlColor);
}
.search__info.center {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
padding-bottom: 40px;
}
.search__info .type {
text-align: center;
margin-bottom: 10px;
}
.search__info .keyword {
text-align: center;
margin-bottom: 10px;
}
.search__info .keyword span {
border: 2px solid var(--htmlColor);
border-radius: 50px;
padding: 10px;
display: inline-block;
margin-bottom: 4px;
}
.search__info .keyword span:hover {
background-color: var(--htmlColor);
color: #fff;
cursor: pointer;
}
.search__desc {
padding: 20px 40px 20px 60px;
margin-bottom: 50px;
border-radius: 50px;
display: inline-block;
background-color: var(--htmlColor);
color: #fff;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='11' cy='11' r='8' stroke='%23ffffff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16.5 16.958L21.5 21.958' stroke='%23ffffff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
background-repeat: no-repeat;
background-position: 22px 17px;
}
.search__click {
margin-top: 10px;
margin-bottom: 30px;
}
.search__click li {
display: inline;
}
.search__click li a {
display: inline-block;
border: 1px solid var(--htmlColor);
border-radius: 50px;
padding: 10px 20px;
margin: 5px 0;
}
.search__click li a:hover {
background-color: var(--htmlColor);
color: #fff;
}
@media (max-width: 600px) {
.search__wrap {
padding: 20px;
}
.search__wrap > span {
font-size: 16px;
margin-bottom: 10px;
}
.search__wrap > h1 {
font-size: 44px;
}
.search__box input {
font-size: 16px;
padding: 12px 30px;
}
}
.search__answers {
border-bottom: 2px dashed var(--htmlColor);
padding-bottom: 40px;
}
.search__answers span {
display: inline-block;
background: var(--htmlColor);
padding: 10px 20px;
color: #fff;
border-radius: 30px;
margin: 3px;
}
.search__missAnswers {
border-bottom: 2px dashed var(--htmlColor);
padding: 40px 0;
}
.search__missAnswers span {
display: inline-block;
border: 1px solid var(--htmlColor);
color: var(--htmlColor);
padding: 10px 20px;
border-radius: 30px;
margin: 3px;
}
.search__audio {
margin-bottom: 10px;
cursor: pointer;
}
.search__audio > span {
width: 24px;
height: 24px;
display: inline-block;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M14 6.3706C14 4.65827 11.9884 3.73774 10.6926 4.85712L7.36317 7.73321C6.99989 8.04704 6.53583 8.21972 6.05576 8.21973L4.49998 8.21974C3.11928 8.21975 2 9.33903 2 10.7197V14.0127C2 15.3934 3.11929 16.5127 4.5 16.5127H6.0558C6.53587 16.5127 6.99993 16.6854 7.36322 16.9992L10.6926 19.8753C11.9884 20.9947 14 20.0741 14 18.3618V12.3662V6.3706Z' fill='%23223547' stroke='%23223547' stroke-width='1.5'/%3E%3Cpath d='M18 14.1215L22.2427 9.87891' stroke='%23223547' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M18 9.87894L22.2427 14.1216' stroke='%23223547' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.search__audio .playing {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15 6.3706C15 4.65827 12.9884 3.73774 11.6926 4.85712L8.36317 7.73321C7.99989 8.04704 7.53583 8.21972 7.05576 8.21973L5.49998 8.21974C4.11928 8.21975 3 9.33903 3 10.7197V14.0127C3 15.3934 4.11929 16.5127 5.5 16.5127H7.0558C7.53587 16.5127 7.99993 16.6854 8.36322 16.9992L11.6926 19.8753C12.9884 20.9947 15 20.0741 15 18.3618V12.3662V6.3706Z' fill='%23223547' stroke='%23223547' stroke-width='1.5'/%3E%3Cpath d='M18 15.3667C18.6279 14.531 19 13.4923 19 12.3667C19 11.2411 18.6279 10.2024 18 9.3667' stroke='%23223547' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M20 18.3667C21.2558 16.6954 22 14.6179 22 12.3667C22 10.1155 21.2558 8.03802 20 6.3667' stroke='%23223547' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
}
.search__result {
position: fixed;
right: 1vw;
top: 1vw;
transform: scale3d(0, 0, 0);
width: 40vw;
height: 40vw;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #fff;
border: 6px solid #946bc5;
}
.search__result.show {
display: flex;
animation: rubberBand 1s 0.6s ease forwards;
}
.search__result .result {
margin-top: 30px;
font-size: 1.4vw;
line-height: 1.4;
}
.search__result .restart {
background: #946bc5;
color: #fff;
border: 0;
font-size: 20px;
padding: 10px 20px;
border-radius: 50px;
margin-top: 10px;
cursor: pointer;
}
@keyframes rubberBand {
from {
transform: scale3d(0, 0, 0);
}
20% {
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(0.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, 0.95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
JAVASCRIPT
이전 처럼 cssProperty 안에 속성에 대한 정보를 배열 안의 객체로 만들어두었습니다.진행을 위한 선택자와 변수를 구성합니다. 그 위에 먼저 데이터를 출력합니다. 오디오를 addEventListener를 이용해서 play에 대한 컨트롤을 할 수 있게합니다. 인풋체크 함수로 정답을 표시,반영, 초기화합니다. 정답체크, 오답보여주기, 시간설정을 할 수 있도록 구성합니다. 게임이 끝났을때 endQuiz 함수에 발생해야하는 이벤트를 구성합니다. 다시 시작할때 restart함수로 초기화합니다.
const searchTime = document.querySelector(".time span");
const searchList = document.querySelector(".search__list");
const searchAnswers = document.querySelector(".search__answers");
const searchMissAnswers = document.querySelector(".search__missAnswers");
const searchStart = document.querySelector(".search__box .start");
const searchInput = document.querySelector("#search");
const searchAudio = document.querySelector("#audio");
const searchAudioBtn = document.querySelector(".search__audio > span");
const searchScoreTotal = document.querySelector(".search__info .num");
const searchScoreNow = document.querySelector(".search__info .now");
const searchResult = document.querySelector(".search__result .result");
const searchResultWrap = document.querySelector(".search__result");
const searchRestart = document.querySelector(".search__result .restart");
let timeReamining = 120, //남은 시간
timeInterval = "",
score = 0, //점수
answers = {}; //새로운 정답
function updateList() {
cssProperty.forEach(data => {
searchList.innerHTML += `<span>${data.name}</span>`;
});
}
updateList();
// 게임 시작하기
function startQuiz() {
// 시작 버튼 없애기 & 속성 리스트 없애기
searchStart.style.display = "none";
searchList.style.display = "none";
// 다시 시작할 때 기존 데이터 초기화
searchAnswers.innerHTML = "";
searchMissAnswers.innerHTML = "";
// 시간 설정
timeInterval = setInterval(reduceTime, 1000);
// 뮤직 추가하기
searchAudioBtn.classList.add("playing");
audio();
// 점수 계산
searchScoreTotal.innerText = cssProperty.length;
// 정답 체크
checkAnswers();
}
// 음악 설정
function audio() {
searchAudioBtn.addEventListener("click", () => {
searchAudioBtn.classList.toggle("playing");
if (searchAudioBtn.classList.contains("playing")) {
searchAudio.play();
} else {
searchAudio.pause();
}
})
searchAudio.play();
}
// 인풋 체크하기
function checkInput() {
let input = event.currentTarget.value.trim().toLowerCase();
if (answers.hasOwnProperty(input) && !answers[input]) {
answers[input] = true;
//정답 표시
searchAnswers.style.display = "block";
searchAnswers.innerHTML += `<span>${input}</span>`;
//점수 반영
score++;
searchScoreNow.innerText = score;
//정답 초기화
searchInput.value = "";
}
}
// 정답 체크하기 : 정답을 객체 파일로 만들기
function checkAnswers() {
cssProperty.forEach(item => {
let answer = item.name.trim().toLocaleLowerCase();
answers[answer] = false;
});
console.log(answers)
}
// 오답 보여주기
function missAnswers() {
searchMissAnswers.style.display = "block";
cssProperty.forEach(item => {
let answer = item.name.trim().toLocaleLowerCase();
if (!answers[answer]) {
searchMissAnswers.innerHTML += `<span>${answer}</span>`;
}
});
}
// 시간 설정하기
function reduceTime() {
timeReamining--;
if (timeReamining == 0) endQuiz();
searchTime.innerText = displayTime();
}
// 시간 표시하기
function displayTime() {
if (timeReamining <= 0) {
return "0:00";
} else {
let minutes = Math.floor(timeReamining / 60);
let seconds = timeReamining % 60;
//초 단위가 한자리수 일 때 0을 추가
if (seconds < 10) seconds = "0" + seconds;
return minutes + ":" + seconds;
}
}
// 게임 끝났을 때
function endQuiz() {
// alert("게임이 끝났습니다.!!!");
// 시작 버튼 만들기
searchStart.style.display = "block";
searchStart.style.pointerEvents = "none";
// 오답 보여주기
missAnswers();
// 음악 끄기
searchAudio.pause();
searchAudioBtn.classList.remove("playing");
// 시간 정지
clearInterval(timeInterval);
// 메세지 출력
searchResultWrap.classList.add("show");
let point = Math.round((score / cssProperty.length) * 100);
searchResult.innerHTML = `게임이 끝났습니다.<br> 당신은 ${cssProperty.length} 개중에 ${score} 개를 맞추었습니다.<br> 당신의 점수는 몇 ${point}점입니다.`;
}
// 다시 시작하기
function restart() {
searchResultWrap.classList.remove("show");
searchAudioBtn.classList.remove("playing");
searchAudio.play();
startQuiz();
timeReamining = 120;
score = 0;
searchScoreNow.innerText = "0";
}
// 버튼 이벤트
searchStart.addEventListener("click", startQuiz);
searchInput.addEventListener("input", checkInput);
searchRestart.addEventListener("click", restart);
728x90
반응형
'Effect' 카테고리의 다른 글
gameEffect01 (1) | 2022.10.24 |
---|---|
sliderEffect07 (0) | 2022.10.24 |
searchEffect06 (1) | 2022.10.21 |
sliderEffect06 (1) | 2022.10.21 |
sliderEffect05 (1) | 2022.10.20 |