博客
关于我
用Vue.js和Webpack开发Web在线钢琴
阅读量:438 次
发布时间:2019-03-06

本文共 2468 字,大约阅读时间需要 8 分钟。

缘起

由于童心未泯,之前在手机上玩过钢琴模拟App,但是手机屏幕太小,始终觉得不过瘾。其实对于我这个连基本乐理都不懂的“乐盲”来说,就算给我一台真正的钢琴,我也玩不转。不过是图个新鲜、权当娱乐罢了。最近刚好入手一台带触摸屏的Lenovo Yoga 4 Pro,这倒给了我新的想象空间:大屏幕玩起来是不是更带感?在Win10应用商店里搜了下,还真有各种模拟钢琴的应用,随便选了一款安装。结果非常令人失望,音效惨不忍听,还各种闪退。这里顺便吐槽下win10的应用商店,里面的很多应用不是经常安装失败,就是经常闪退,简直没法用啊。作为一名前端开发和坚定的Web支持者,客户端不好用果断转向Web啊。本着尽量不重造轮子的原则,先在网上搜了一下。百度的搜索结果几乎都是那一个例子,也不知道是哪位哥们写的,被到处引用。就那么几个键,怎么玩?Google的结果也不尽如人意,不是打不开就是加载半天。算了,还是自己动手吧。

准备

我们知道,HTML5有音频接口,播放声音自然不在话下。这模拟钢琴自然需要各种音阶的音频文件吧,于是在网上搜了一通,找齐了88键钢琴的音频文件。为什么钢琴有88个键?别问我,我是乐盲。看看这张钢琴示意图就知道了:

开工

最近一直在用Vue.js开发项目,配合Webpack神器构建打包,开发前端项目从来没有如此方便。在此要特别感谢Vue.js的作者Evan You尤雨溪(), 给我们贡献了这么好用的框架。

新建一个Vue.js项目非常简单,可以用官方推荐的脚手架命令行工具创建新工程。首先安装这个工具:

npm install -g vue-cli

安装好后执行命令生成工程模板:

vue init webpack piano

这里我们用webpack作为构建工具,你也可以使用browserify。

就这么简单,一个Vue.js project诞生了,而且Webpack已经配置好。接下来执行命令安装相关的node模块:

npm install

如果一切顺利的话,项目就可以跑起来了:

npm run dev

访问就可以看到默认的欢迎界面。至此,项目的搭建算是完成了。

界面

现在开始写界面。虽然是乐盲,钢琴键盘上有哪些键还是要搞清楚的。对于标准的88键钢琴,总共有88个键,其中52个白色键,36个黑色键。分为低音区、中音区和高音区,每个区有三组。对于我们画界面来说,重要的是找出其中的规律。最两端的两组先不管,其他的分组看上去都是一样的:三白夹两黑跟着四白夹三黑。

怎么实现这个界面布局呢?很简单,黑白键都用button元素表示,设置好宽高、背景色和边框。白色的自然定位并排铺开,黑色的用绝对定位,计算出对应的坐标。这里有个小细节,就是黑白键的DOM元素排列最好跟各音阶的先后顺序对应,这样在计算黑键坐标就比较方便。

既然有七个组的界面是一模一样的,我们就把一组设计成一个组件好了。用Vue.js开发组件真的是太方便了,一个.vue文件包含HTML template、script和style,就构成了一个独立的组件。每组的音阶范围不一样,通过组件的props设定。来看组件的源码文件Group.vue

逻辑并不复杂,关键是处理细节。按键的宽度是用百分比的,高度固定。黑键的坐标计算逻辑在方法calcLeft里,具体看代码好了,code will talk.

你可能有个疑问:音频内容哪来的?继续看。

音频处理

前面提到过,我从网上找到了钢琴的88音阶的音频文件,都是mp3格式的。但是我不想让88个音分散在88个.mp3文件里,不然在弹奏的时候一个个文件下载,可不太好。怎么办呢?我们知道图片可以转成base64的字符串显示在DOM里。其实音频文件也一样,用data:audio/mpeg;base64,XXXXXX就可以了。写了个Node程序,一次性将所有Mp3文件都转成了base64字符串数组备用:

var fs = require('fs');var file = 'notes.json';// function to encode file data to base64 encoded stringfunction base64_encode(file) {    // read binary data    var bitmap = fs.readFileSync(file);    // convert binary data to base64 encoded string    return new Buffer(bitmap).toString('base64');}fs.readdir('.', function(error, files) {    var content = "";    files.forEach((f, index) => {        if(/^\d/.test(f)) {            var data = base64_encode(f);            content += `"${data}",\n`;        }    });    fs.writeFileSync(file, content);});

数组内容放在一个单独的文件里,作为模块引入。数组元素的顺序就是音阶从低到高的顺序。HTML5的Audio对象,支持从构造函数传入base64数据,然后调用play()就可以播放声音了。

没有触摸屏咋玩?还有键盘啊。简单起见,用三排字母按键对应中音区的三个组。监听键盘keydown事件,通过keyCode区分不同的键,播放对应的音频内容就好了。

总结

这个过程并不复杂,就是布局和音频处理需要处理一些细节。代码写得很仓促,有些地方可以重构下。完整的源码可以在我的找到。喜欢的欢迎star,有闲工夫也可自己改进。最终效果点击这里:

转载地址:http://lzmyz.baihongyu.com/

你可能感兴趣的文章
MySQL - ERROR 1406
查看>>
mysql - 视图
查看>>
MySQL - 解读MySQL事务与锁机制
查看>>
MTTR、MTBF、MTTF的大白话理解
查看>>
mt_rand
查看>>
mysql -存储过程
查看>>
mysql /*! 50100 ... */ 条件编译
查看>>
mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
查看>>
mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
查看>>
mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
查看>>
mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
查看>>
MySQL 8.0 恢复孤立文件每表ibd文件
查看>>
MySQL 8.0开始Group by不再排序
查看>>
mysql ansi nulls_SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 什么意思
查看>>
multi swiper bug solution
查看>>
MySQL Binlog 日志监听与 Spring 集成实战
查看>>
MySQL binlog三种模式
查看>>
multi-angle cosine and sines
查看>>
Mysql Can't connect to MySQL server
查看>>
mysql case when 乱码_Mysql CASE WHEN 用法
查看>>