吉他初学者学习网站搭建系列(2)——如何实现一个乐谱播放器

吉他谱如何自动播放?个人乐谱播放网站YUERGS搭建

背景

我是一个吉他弹唱爱好者,我的吉他谱都是自己在网络上收集到的图片,一般一首曲子都是好几张图片组成的。当我在弹吉他时,我希望图片可以按照一定的速度自动播放,可是目前现有的一些app,比如finger,在吉他谱达到一定数量后,没法继续添加乐谱,这让我决定自己动手做一个简单版本的吉他谱自动播放网站,成为了我练吉他必不可少的工具。

这个网站目前我部署在了gitee,网址是:https://tryiscool.space/music-score/#/score

介绍

网站布局

在这里插入图片描述
大概可以猜出,我是陶喆的歌迷,嘿嘿

技术栈

vue3 + Vite + Vuetify
纯前端,不过图片的索引文件借助了node.js的能力来生成。

代码结构

在这里插入图片描述

根组件App.vue,调用了子组件Score.vue和Chord.vue,分别用于展示乐谱和查和弦。Score.vue组件调用了Viewer.vue组件,用于吉他谱的全品展示和自动播放。

下面我介绍下我吉他谱的文件结构

吉他谱文件结构

在这里插入图片描述
如上图所示,我将吉他谱放在public目录下,方便引用。一个根目录是data,下面每一首歌都按照歌手-歌名的命名方式,文件夹下放这首歌的吉他谱,按照顺序用数字命名。

我在每次打包时,会调用一段后端的代码,将这个文件目录转换为一个src/assets/directory.json文件,大致内容如下图:
在这里插入图片描述
可以看到,是一个嵌套结构,每一个item包含了一些固定字段,如类型、名称、标题、作者、是否加密、文件时间、文件大小、以及文件夹下的子文件。这些信息都是通过File方法进行提取,最终可以直接展示。

如果有一些谱子,你不希望展示给公众,你想加密,有什么方法吗?
答案是有的。我这里使用的方法是,通过crypto-js库,将一段文本,通过密匙进行加密,最后用户输入正确密码,可以解密出对应文本,匹配正确则展示对应乐谱。这种方法的好处是简单,但是想要破解难度估计也不大,不过对于乐谱这种没有太多价值的东西,应该没有人想花时间破解这玩意儿。

还有一些手段,比如对图片像素进行加密,比如异或加密方法,我们知道,一个数字和另一个数字异或两次就等于其自身:

a === a^b^b // true

因此,可以利用一个数字密码,对每个像素先进行一次异或运算,然后在解密时,再异或一次,得到原图。不过需要考虑像素值超过255,这个可以再考虑如何解决。

滚动播放

在这里插入图片描述
我这边实现了图片放大缩小、滚动速度调整和全屏的功能。
放大缩小功能很简单,用一个容器,将图片包在里面,宽度100%,用flex朝下的布局方式顺序布局。而容器居中定位即可。缩放本质是改变容器的宽度。

滚动播放如何实现?
也很简单,定时调整容器元素的scrollTop,利用requestAnimationFrame可以重绘的特性,利用一些计数方法来控制滚动速度。为了让网页滚动得比较流畅,最好每次重绘时,滚动条高度+1像素,像素差过大,不够丝滑。代码如下:

const speedList = [5, 4, 3, 2, 1];
export default {
methods: {
  // 调整滚动速度
  speedUp() {
      this.speed = (this.speed + 1) % speedList.length;
    },
  // 滚动
  moveDown() {
      if (requestIns) {
        cancelAnimationFrame(requestIns);
        requestIns = 0;
      } else {
        this.run();
      }
    },
   //  重绘
   run() {
      times++;
      if (times > speedList[this.speed]) {
        times = 0;
        this.$refs.viewContainer.scrollTop += 1;
        if (
          this.$refs.viewContainer.scrollTop ===
          this.$refs.viewContainer.scrollHeight -
            this.$refs.viewContainer.clientHeight
        ) {
          this.moveDown();
          return;
        }
      }
      requestIns = requestAnimationFrame(this.run);
    },
  }
}

全屏功能利用现有的fullscreen API,代码如下:

    fullScreen() {
      if (!document.fullscreenElement) {
        this.$refs.scoreContainer.requestFullscreen();
      } else {
        document?.exitFullscreen();
      }
    },

欢迎交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HouGISer

HouGiser需要你的鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值