こんにちは!Qiita初投稿のim90と申します。現在、フロントエンドエンジニアを目指して勉強中です。
自分で何か作ってみるのが一番勉強になる、とよく聞くので、初めて自作アプリを作ってみました。
今回は、音姫(トイレの音なるやつ)をつくってみました。
全然大した事はしていないのですが、思い出としてこちらに残しておきたいと思います。
#実装した機能
- スタートボタンを押したら音が流れる(25秒)
- ストップボタンを押したら音が止まる
- 音が流れている間は、スタートボタンを無効にする
- ストップ → スタートの際は、改めて25秒間音を流す
- 残り時間を表示する
シンプルです
探しましたが本物の音姫の音が無かったので、今回は波の音を使いました。
音が出るデモが無くて申し訳ないです・・・。
#コード(HTML、CSS、JavaScript)
index.html
<body>
<div class="container">
<div class="contents-wrapper flex-box">
<!-- speaker -->
<div class="left">
・・・・・・・・・・・
・・・・・・・・・・・
・・・・・・・・・・・
・・・・・・・・・・・
・・・・・・・・・・・
・・・・・・・・・・・
・・・・・・・・・・・
</div>
<!-- ↓ display -->
<div class="right">
<div class="btn start" onclick="start()"><audio src="sounds/wave1.mp3" loop="true"></audio>⇨<br>start</div>
<div class="btn stop" onclick="stop()">■<br>stop</div>
<div class="remainingTime">残り秒数:<span class="lighting"></span></div>
</div>
<!-- ↑ display -->
<div class="description">
<p>手をかざすと25秒水の流れる音がします。
<br>途中でボタンを押すと延長します。
</p>
</div>
</div>
<footer>TOTO</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="index.js"></script>
</body>
</html>
style.css
*{
margin: 0 auto;
padding: 0;
box-sizing: border-box;
}
body {
margin: 3rem;
padding: 2rem;
width: 30rem;
height: 20rem;
text-align: center;
border: .5px solid lightgrey;
box-shadow: 1rem 1rem 1rem 1rem rgba(0, 0, 0, .4);
user-select: none;
}
.contents-wrapper{
padding: 1.5rem;
height: 10rem;
}
.left{
width: 8rem;
float: left;
font-size: 10px;
padding: 0;
}
.right{
float: right;
width: 13rem;
padding: 1rem 0;
}
.btn{
height: 3rem;
width: 6rem;
margin-bottom: 1rem;
box-shadow: .1rem .1rem .1rem .1rem rgba(0, 0, 0, .4);
cursor: pointer;
}
.btn:active{
box-shadow: none;
}
.start{
float: left;
background-color: black;
color: whitesmoke;
}
.disabled{
background-color: rgba(0, 0, 0, .8);
pointer-events: none;
}
.stop{
border: 1px solid lightgray;
float: right;
}
.remainingTime{
clear: both;
text-align: left;
font-size: 14px;
}
.description{
clear: both;
}
footer{
margin-top: 3.5rem;
}
index.js
var startButton = document.querySelector('.start');
var stopButton = document.querySelector('.stop');
var light = document.querySelector('.lighting');
var audio = new Audio('sounds/wave1.mp3');
audio.loop = true;
var timeoutID;
var playing = true;
//スタートボタンを押したら音を流す
function start(){
audio.play();
playing = true;
light.innerHTML = 25;
startButton.classList.add("disabled");
var totalTime = 25000; // 25sec
var oldTime = Date.now();
var timerID = setInterval(function(){
var currentTime = Date.now();
var diff = currentTime - oldTime;
var remainMsec = totalTime - diff;
var remainSec = Math.ceil(remainMsec / 1000);
light.innerHTML = remainSec;
if(remainSec <= 0){
clearInterval(timerID);
light.innerHTML = "";
startButton.classList.remove("disabled");
}
if(playing === false){
clearInterval(timerID);
light.innerHTML = "";
}
}, 1000);
timeoutID = window.setTimeout(() => {
audio.pause();
audio.currentTime = 0;
}, 25000);
}
//ストップボタンを押したら音をストップさせる
function stop(){
audio.pause();
clearTimeout(timeoutID);
audio.currentTime = 0;
playing = false;
startButton.classList.remove("disabled");
}
#作成フロー(JavaScript)
- 変数の定義
- スタートボタンを押すと音が流れる関数をつくり、25秒でタイムアウトするようにする(
setTimeout()
) - ストップボタンを押すと音が止まる関数をつくる
- 再生時はスタートボタンを無効にする(このままだとスタート関数が重複して実行できてしまうため)
- ストップボタンを押して再生したときに、最初から音が流れる(
clearTimeout()
)この作業をしないと、ストップ → 再生したときに音が中途半端に切れてしまいました。
#作ってみて
実は今回現役プログラマーの方に見て頂いたのですが、下記のアドバイスを頂きました。
- onclickよりかは、addEventListenerを使った方が見やすい。(どの要素と関数が紐付いているかが一目で分かりやすいため)
- 現場では
==
よりも===
を使う事が求められる。こちらの記事で分かりやすく説明されていました。JavaScript 忘れがちな === と == の違い
あとは、var
でなくlet
とconst
に書き直せば良かったな~、と今更ながら思いました・・・
また、スピーカーの見た目を再現するのに・・・
を何個も書いたのですが、もっと良い方法があるような気もします。
お気づきの点がございましたら、もっとこうした方が良いなど、ぜひアドバイス頂けますと幸いです。
とりあえず今は次のアプリに挑戦してみようと思います!ご覧頂き、ありがとうございました。