查看原文
其他

HTML5 + Javascript 写出一个钢琴

听见下雨声 逛逛GitHub 2021-08-19

首发:GitHubClub

原文:juejin.im/post/6879708939190009869

学生时代的我们如果有像郎朗一样的琴技,想必追起女生会非常的容易,但在以前,一架钢琴对普通家庭来说,消费还蛮高的,所以我们不如自己写一架属于自己的钢琴,哈哈,虽然音效不如真的钢琴,但是能写出来,还挺有成就感的。

这里不会用到很复杂或者很难的知识,只要按照文章中的步骤一步一步来,最后都可以做出来。心动不如行动,我们赶快开始吧。
该项目的 Gitee 地址:关注微信公众号 逛逛GitHub,回复 钢琴 获取。
绘制出一个钢琴
首先我们要创造出钢琴的琴键,这里用ul+li当钢琴的骨架,其中div代表钢琴白键,p代表钢琴黑键。
<ul>
<li><div></div><p></p></li>
<li><div></div><p></p></li>
<li><div></div></li>
<li><div></div><p></p></li>
<li><div></div><p></p></li>
<li><div></div><p></p></li>
<li><div></div></li>
<li><div></div></li>
</ul>


写完了骨架我们还要给它加一点样式,至少让琴键的外表看起来更像真正的钢琴。
/*-------钢琴部分--------*/
ul{
width:480px;
height:360px;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
}
li{
float:left;
list-style-type: none;
position: relative;
}
li>div{
height: 360px;
width: 60px;
background: rgba(255,255,255,.3);
border: 1px solid;
border-color:rgba(0, 0, 0, .8);
border-bottom-left-radius : 8px;
border-bottom-right-radius: 8px;
box-sizing: border-box;
box-shadow: /*inset 3px 0 10px #c9c6c6,*/
inset 5px -8px 0 #00000023;
text-align: center;
display:table-cell;
vertical-align: bottom;
}
li:not(:last-child)>div{
border-right: none;
}
li>div:hover{
background: rgb(255, 97, 97);

}
/* 当白键按下时的样式 */
.white_active{
box-shadow: inset 3px -2px 0 #00000036;
background: linear-gradient(45deg, rgba(255,255,255,.7), rgba(255,255,255,.5));
}

li>p{
height: 200px;
width: 40px;
background-color: #000;
border-bottom-left-radius : 5.5px;
border-bottom-right-radius: 5.5px;
box-shadow: inset 5px -7px 0 #2c2c2c;
position: absolute;
top:0;
left: 40px;
z-index: 999;
}
li>p:hover{
background: linear-gradient(45deg, #4c4c4c, #444444);
}
/* 当黑键按下时的样式 */
.black_active{
box-shadow:inset 3px -5px 0 #2c2c2c;
}
现在的钢琴就是下面这个样子,外形已经有了,但只是一个画面,我们点击琴键听不到声音。
给钢琴添加声音
钢琴有了画面,我们就要开始添加声音了,这里要用到js,首先把音源引入。
// 给钢琴添加音频
for (var i = 1; i <= 8; i++) {
var addaudio = document.createElement("audio");
addaudio.setAttribute("src", "audios/" + "w" + i + ".ogv");
document.body.appendChild(addaudio);
}
for (var i = 1; i <= 5; i++) {
var addaudio = document.createElement("audio");
addaudio.setAttribute("src", "audios/" + "b" + i + ".ogv");
document.body.appendChild(addaudio);
}
音源现在引入了,我们只需要让钢琴琴键按下时,播放对应的音频就行了。这里我们可以实现两种演奏钢琴的方式,一种是直接点击琴键弹奏,另一种是通过我们的键盘按键来弹奏。
使用键盘上的 S~L键操作钢琴白键,E,R,Y,U,I操作钢琴黑键。我们先用js 获取到相关的 dom。

let audios = document.getElementsByTagName("audio"),
buttons = document.querySelectorAll("ul>li>div"),
blacks = document.querySelectorAll("ul>li>p");



①鼠标点击琴键
前面我们已经获取到琴键的 dom 了,现在用 for 循环按顺序给琴键的 dom 添加对应的鼠标事件就行了。
for (var i = 0; i < 8; i++) {
buttons[i].index = i;
buttons[i].onmousedown = function () {
//alert(this.index);
buttons[this.index].classList.add('white_active')
audios[this.index].load();
audios[this.index].play();
};

buttons[i].onmouseup = function () {
buttons[this.index].classList.remove('white_active')
};
}
for (var i = 0; i < 5; i++) {
blacks[i].index = i + 8;
blacks[i].onmousedown = function () {
//alert(this.index);
blacks[this.index-8].classList.add('black_active')
audios[this.index].load();
audios[this.index].play();
//alert(audios[this.index].src);
};

blacks[i].onmouseup = function () {
blacks[this.index-8].classList.remove('black_active')
};
}


②键盘当做琴键
首先我们要知道按键的keyCode键码值,这样才能给按键添加事件。知道相关按键的键值码后放到一个数组里,然后用 for 循环给每个按键添加对应的事件。
// 操作键盘钢琴白键发出声音
var keyCodes = new Array(83, 68, 70, 71, 72, 74, 75, 76, 69, 82, 89, 85, 73);
document.body.onkeydown = function (e) {
for (var i = 0; i < keyCodes.length; i++) {
if (e.keyCode == keyCodes[i]) {
if (i < 8) {
buttons[i].classList.add('white_active');
} else {
blacks[i-8].classList.add('black_active');
}
audios[i].load();
audios[i].play();
}
}
};

// 操作键盘钢琴黑键发出声音
document.body.onkeyup = function (e) {
//document.title=e.keyCode;
for (var i = 0; i < keyCodes.length; i++) {
if (e.keyCode == keyCodes[i]) {
if (i < 8) {
buttons[i].classList.remove('white_active');
} else {
blacks[i-8].classList.remove('black_active');
}
}
}
};


到这里我们的钢琴已经能进行弹奏了。
添加曲库
光有钢琴没有曲子怎么行呢,我们可以自己在网上找个曲谱,然后添加到对应的地方就可以了。
首先把布局写出来,这里就不添加那些花里胡哨的样式了。
<div>
请输入简谱:
<input type="text" id="song" placeholder="请输入歌曲名">
<button id="check">确定</button>
</div>


然后开始写逻辑部分,scroe 对象是用来存放歌曲信息的,不想去网上找歌曲信息的,可以直接复制最后面部分的简谱。格式类似于 {‘歌曲名’:‘歌词和简谱’} ,这里可以用模板字符串的形式。

var scroe = {};

var numReg = /[1-9]/g;
var wordReg = /[\u4e00-\u9fa5]+/g;


var str;
var shows;
var words;
var wordsIndex;
var wordsCurrent;
var current;


function play(){
buttons.forEach((el)=>el.classList.remove('show'))
var songName = song.value;

if(songName === ''){
return alert('请输入歌曲名')
}

if(scroe.hasOwnProperty(songName)){
str = scroe[songName];
shows = str.match(numReg);
words = str.match(wordReg);
wordsIndex = 0;
wordsCurrent = 0;
current = 0;
console.log(songName)
buttons[shows[0]/1 - 1].classList.add('show');
text.textContent = words[0]
}else{
return alert('您输入的歌曲名尚未加入曲库')
}
}

check.addEventListener('click',play)


现在的效果图就是下面这个样子👇。
添加歌词和琴键提示
布局最上面的那部分代码里已经写好了,直接开始写逻辑。
function start(){
// 显示歌词的部分
if(wordsCurrent>=words[wordsIndex].length-1){
wordsCurrent = 0;
wordsIndex++;
text.textContent = words[wordsIndex]
}else{
wordsCurrent++
}


if(current === shows.length-1){
buttons[shows[shows.length-1]/1 - 1].classList.remove('show');
return console.log('演奏结束',current)
}

var showButton = shows[current+1]/1 - 1;
var hiddenButton = shows[current]/1 - 1;

buttons[hiddenButton].classList.remove('show');
buttons[showButton].classList.add('show');
current++
}

然后再在对应的按键事件和鼠标点击事件加上这段代码。

i == shows[current]-1 ? start() : '';

现在我们想要的效果基本已经实现。

加些小的装饰
我们可以给钢琴按键加上对应的编号,方便我们弹奏。
// 给琴键加上数字
buttons.forEach((el,index)=>el.textContent = index+1)

window.addEventListener('keydown',function(e){
if(e.keyCode == 86){
if(buttons[0].textContent != ''){
buttons.forEach((el)=>el.textContent = '')
}else{
buttons.forEach((el,index)=>el.textContent = index+1)
}
}
})


此时琴键上已经有了对应的编号。我们还可以通过快捷键V实现编号显示与隐藏的切换。
我们再给钢琴加个使用说明。
let x = document.getElementById("btn-js"),
y = document.getElementById("js"),

//介绍的隐藏与显示
function hide() {
y.style.display === "block" ? y.style.display = "none" : y.style.display = "block"
}

x.addEventListener('click',hide);


可以看到在演奏歌曲的同时也显示歌词了。
现在一个简易版的钢琴已经做出来了,外形是不是和真的钢琴挺像的。赶紧用它来演奏歌曲吧😀。
分享一些歌曲的简谱
该项目的 Gitee 地址:关注微信公众号 逛逛GitHub,回复 钢琴 获取。
推荐阅读
1. 给新手的 11 个 Docker 免费上手项目
2. 我在 GitHub 上找到开源的《植物大战僵尸》
3. 推荐 22 款好用的命令行工具
4. 百度网盘突然大调整


在看 

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存