오늘은 Javascript로 피아노를 만들어 보았다.
소스코드
index.html
<!DOCTYPE html>
<html lang="ko" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js" defer></script>
<link rel="stylesheet" href="style.css">
<title>Piano</title>
</head>
<body>
<div class="wrapper">
<header>
<h2>ONSTAR PIANO</h2>
<div class="column volume-slider">
<span>Volume</span>
<input type="range" min="0" max="1" value="0.5" step="any">
</div>
<div class="column keys-checkbox">
<span>Show Keys</span>
<input type="checkbox" checked>
</div>
</header>
<ul class="piano-keys">
<li class="key white" data-key="a"><span>a</span></li>
<li class="key black" data-key="w"><span>w</span></li>
<li class="key white" data-key="s"><span>s</span></li>
<li class="key black" data-key="e"><span>e</span></li>
<li class="key white" data-key="d"><span>d</span></li>
<li class="key white" data-key="f"><span>f</span></li>
<li class="key black" data-key="t"><span>t</span></li>
<li class="key white" data-key="g"><span>g</span></li>
<li class="key black" data-key="y"><span>y</span></li>
<li class="key white" data-key="h"><span>h</span></li>
<li class="key black" data-key="u"><span>u</span></li>
<li class="key white" data-key="j"><span>j</span></li>
<li class="key white" data-key="k"><span>k</span></li>
<li class="key black" data-key="o"><span>o</span></li>
<li class="key white" data-key="l"><span>l</span></li>
<li class="key black" data-key="p"><span>p</span></li>
<li class="key white" data-key=";"><span>;</span></li>
</ul>
</div>
</body>
</html>
style.css
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: radial-gradient(circle farthest-corner at 32% 106%,#ffe17d 0%,#ffcd69 10%,#fa9137 28%,#eb4141 42%,transparent 82%) , linear-gradient(135deg,#234bd7 12%,#c33cbe 58%);
}
.wrapper {
padding: 35px 40px;
border-radius: 20px;
background: #ffffff;
box-shadow: 0 0 20px #ffffff;
}
.wrapper header {
display: flex;
color: #B2B2B2;
align-items: center;
justify-content: space-between;
}
header h2 {
font-size: 1.6rem;
background: radial-gradient(circle farthest-corner at 32% 106%,#ffe17d 0%,#ffcd69 10%,#fa9137 28%,#eb4141 42%,transparent 82%) , linear-gradient(135deg,#234bd7 12%,#c33cbe 58%);
color: transparent;
-webkit-background-clip: text;
}
header .column {
display: flex;
align-items: center;
}
header span {
font-weight: 500;
margin-right: 15px;
font-size: 1.19rem;
background: radial-gradient(circle farthest-corner at 32% 106%,#ffe17d 0%,#ffcd69 10%,#fa9137 28%,#eb4141 42%,transparent 82%) , linear-gradient(135deg,#234bd7 12%,#c33cbe 58%);
color: transparent;
-webkit-background-clip: text;
}
header input {
outline: none;
border-radius: 30px;
}
.volume-slider input {
accent-color: #ffe277;
}
.keys-checkbox input {
height: 30px;
width: 60px;
cursor: pointer;
appearance: none;
position: relative;
background: #ededed;
}
.keys-checkbox input::before {
content: "";
position: absolute;
top: 50%;
left: 5px;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ffffff;
transform: translateY(-50%);
transition: all 0.3s ease;
}
.keys-checkbox input:checked::before {
left: 35px;
background: radial-gradient(#ffe17d,#ffcd69,#fa9137,#eb4141);
}
.piano-keys {
display: flex;
list-style: none;
margin-top: 40px;
}
.piano-keys .key {
cursor: pointer;
user-select: none;
position: relative;
text-transform: uppercase;
}
.piano-keys .black {
z-index: 2;
width: 44px;
height: 140px;
margin: 0 -22px 0 -22px;
border-radius: 0 0 5px 5px;
background: linear-gradient(#333, #000);
}
.piano-keys .black.active {
box-shadow: inset -5px -10px 10px rgba(255,255,255,0.1);
background:linear-gradient(to bottom, #000, #434343);
}
.piano-keys .white {
height: 230px;
width: 70px;
border-radius: 8px;
border: 1px solid #000;
background: linear-gradient(#fff 96%, #eee 4%);
}
.piano-keys .white.active {
box-shadow: inset -5px 5px 20px rgba(0,0,0,0.2);
background:linear-gradient(to bottom, #fff 0%, #eee 100%);
}
.piano-keys .key span {
position: absolute;
bottom: 20px;
width: 100%;
color: #A2A2A2;
font-size: 1.13rem;
text-align: center;
}
.piano-keys .key.hide span {
display: none;
}
.piano-keys .black span {
bottom: 13px;
color: #888888;
}
@media screen and (max-width: 815px) {
.wrapper {
padding: 25px;
}
header {
flex-direction: column;
}
header :where(h2, .column) {
margin-bottom: 13px;
}
.volume-slider input {
max-width: 100px;
}
.piano-keys {
margin-top: 20px;
}
.piano-keys .key:where(:nth-child(9), :nth-child(10)) {
display: none;
}
.piano-keys .black {
height: 100px;
width: 40px;
margin: 0 -20px 0 -20px;
}
.piano-keys .white {
height: 180px;
width: 60px;
}
}
@media screen and (max-width: 615px) {
.piano-keys .key:nth-child(13),
.piano-keys .key:nth-child(14),
.piano-keys .key:nth-child(15),
.piano-keys .key:nth-child(16),
.piano-keys .key :nth-child(17) {
display: none;
}
.piano-keys .white {
width: 50px;
}
}
main.js
const pianoKeys = document.querySelectorAll(".piano-keys .key");
volumeSlider = document.querySelector(".volume-slider input");
keysCheckbox = document.querySelector(".keys-checkbox input");
let allKeys = [],
audio = new Audio("sounds/*");
const playTune = (key) => {
audio.src = `sounds/${key}.wav`;
audio.play();
const clickedKey = document.querySelector(`[data-key="${key}"]`);
clickedKey.classList.add("active");
setTimeout(() => {
clickedKey.classList.remove("active");
}, 150);
}
pianoKeys.forEach(key => {
allKeys.push(key.dataset.key);
key.addEventListener("click", () => playTune(key.dataset.key));
});
const handleVolume = (e) => {
audio.volume = e.target.value;
}
const showHideKeys = () => {
pianoKeys.forEach(key => key.classList.toggle("hide"));
}
const pressedKey = (e) => {
if(allKeys.includes(e.key)) {
playTune(e.key);
}
}
keysCheckbox.addEventListener("click", showHideKeys);
volumeSlider.addEventListener("input", handleVolume);
document.addEventListener("keydown", pressedKey);
실행 화면
사운드 파일
소스코드 링크
'JavaScript' 카테고리의 다른 글
JavaScript Clock (0) | 2023.01.18 |
---|