【Simple-Notaion】我用vite+ts+vue开发了一个简谱渲染应用,别人问我这有什么意义?

116 阅读4分钟

意义

前排先挂一个截图展示以及网站: Simple Notation - 简谱展示工具 simple-notation.vercel.app_.png

也可以直接安装库来体验(好像漏了通过库开发使用的教程,回去补一下):

npm i simple-notation

就像标题提到的,有人问我我开发这个有什么意义,这让我想到了我最初学前端的原因,因为前端写什么就能看到什么,能写出我想要的页面,能做我想做的东西。开发的初心不是为了进入社会混口饭吃,也不是为了整天写那个没有营养的curd,是为了让自己开心。

我有一个想法,我也有能力去实现,写出来的东西能让我感到满足,我觉得这就是意义。不是什么我发誓要做一个开源大佬,或者我要写出一个让别人都目瞪口呆的作品。只是我想了,我做了,我爽了,就够了。

应用设计

应用设计总体上修改过很多次,来来回回的重构,一是没经验,二是一开始的考虑确实不够,后面发现有新的需求又得把前面的推倒重来。但目前总体上是有一个确定的需求:

  1. 用户进入页面,通过文本编辑,实时渲染
  2. 支持基础的简谱功能,能完成常见乐谱的编写
  3. 编写完成后可以打印,可以使用打印窗口保存pdf

用户界面

一开始是没有用户界面的,只是想开发一个库,但是开发后总需要一个测试调试的地方。所以一开始就写了一个ts文件来测试,后来因为陆续加东西,索性就把测试页面改成了应用界面,然后部署在了vercel上,方便我访问使用。

image.png

可以看到页面基本上没什么东西,主要就是操作区域和教程区域,为了更好了解怎么使用,又加入了示例。

简谱渲染

这一部分是这个库的核心,代码量也是很大,铺了很多文件来实现。到后期往往自己都记不清类型定义(得赶紧补点注释了),但后续多次简化优化,逻辑已经清晰很多了。

image.png

我认为做过的几次优化,最有价值的就是封装了基类SNBOX:

import { SNBorderLayer } from '@layers';
import { SNBorderBoxOptions, SNBoxType, SNPoint } from '@types';
import { Logger } from '@utils';

export class SNBox {
  parent: SNBox | null;
  type: SNBoxType;
  x: number;
  y: number;
  width: number;
  height: number;
  innerX: number;
  innerY: number;
  innerWidth: number;
  innerHeight: number;
  paddingX: number;
  paddingY: number;

  constructor(
    parent: SNBox | null,
    type: SNBoxType,
    x: number,
    y: number,
    width: number,
    height: number,
    padding?: number | number[],
  ) {
    // do something...
  }

  resize() {
    // do something...
  }

  setWidth() {
    // do something...
  }

  setHeight() {
    // do something...
  }

  getSNPointByLayer() {
    // do something...
  }

  drawBorderBox() {
    // do something...
  }

  drawOuterBox() {
    // do something...
  }

  drawInnerBox() {
    // do something...
  }

  drawBox() {
    // do something...
  }
}

有了基类,后续所有布局的操作,都简化了很多,基本各自处理各自的逻辑。

还有一个就是重构了渲染逻辑,一开始的构思是边解析边渲染,然后发现了一些问题,比如不好均匀分布音符,需要先知道一行有多少音符,给权重来均匀渲染。因此后来重构改为了先解析数据,保存一个结构体,然后根据结构体渲染页面。

这样修改后带来的好处还有解析和渲染的解耦,正好今天有人提了issue,询问是否支持abc渲染。虽然目前不支持,但是解耦以后的逻辑可以使用单独的abc解析器对接结构体,避免重构渲染逻辑。

打印保存

当用户编辑完以后,需要留存这次编辑,比如产出一个乐谱,那么要么是使用svg产出一个截图,要么是直接打印。目前选择了先实现打印,因为当前的逻辑要处理分页,正好和打印一起处理。

image.png

有产出以后这个页面才算是有完整的流程,从编辑到保存。

结语

这个项目纯粹是兴趣使然,没有什么目标,需求也是想一出是一出,也许目标就是为了让项目更有趣,能在使用的时候感受到一点乐趣吧。