Learn Vexflow By Example
vexflow 是一个 html 渲染五线谱的库,它有两套 API,一套是 low-level 的,一套是 high-level 的,考虑到我的需求实际上并非是去渲染乐谱,这里去学习它的 low-level API,下面全部用 vexflow 去指代它 low-level 的 API。
学习这些概念及其相关操作、相互关系就是学习 vexflow,这里学习一下vexflow的如下概念:
- Renderer
- Context
- Stave
- StaveNote
- Formatter
Renderer, Context
参考:https://github.com/0xfe/vexflow/wiki/Understanding-Renderer-&-Context
使用 vexflow 时,一般会有这样的样板代码,它引用一个 div 或 canvas 元素设置相应空间,并获取 context,其用于渲染五线谱。
1 |
|
Renderer 对应渲染五线谱的空间,其可调整渲染方式:svg 或 canvas。Renderer 只有两个方法——调整大小或获取 context。
context 提供了大量进行图形绘制的方法,它抽象了底层细节,使同一套接口能适用于 SVG 和 canvas。但 context 的方法太过底层,一般没有需要直接使用 context,而是利用 Stave,Note,Voice 等类的接口进行绘制。比如 Stave 可能会这样调用stave.setContext(context).draw()
,这暗示了它会利用 context 的方法进行绘制。
Renderer 使用 svg 作为渲染方式时需要注意,其会在引用的 div 下新建一个 svg 元素,而如果这个元素下面原来就存在其它 Renderer,其不会受影响。这导致在 React 的 StrictMode 下会渲染重复的元素,因此需要在清理函数中删除 div 下所有子元素。canvas 似乎无此影响,但尚不知是否有其它 bug。这里只使用 svg。
上面的代码会得到下面的结果,这里加上一个 border 方便查看:
1 |
|
白如纸,得加点东西上去。
五线谱
Stave 即五线谱,StaveNote,Voice 等实体需要依赖 Stave 进行绘制(它们都继承一个 Element 类)。
创建五线谱是 trival 的:
1 |
|
Stave 的构造器接受三个参数——x,y 轴的偏移量和长度,其中 y 轴偏移量即使设置为 0,其也不会真正地挨着顶部,这是为上加线/间的音符预留的空间。
addClef
方法去设置谱号,可选项颇多,但常用的顶多 treble 汗 bass。
addTimeSignature
设置拍号,语法如6/8
,表示八分音符为一拍,一小节六拍。
addKeySignature
设置调号,调号按大调来,比如 G 表示 G 大调,在 F 上有升号。
一个严重需要注意的地方是,Stave 的谱号,拍号,调号等属性,在业务逻辑上是没有影响的,只用于绘图!比如我设置拍号为四四拍,但完全可以在一个小节里塞上 10 个全音符;比如我设置谱号为低音谱号,绘制一个 C4,它仍旧会绘制在下加一线上!它们的配置都在它们自己身上,并不依赖 Stave 的配置。
音符,Formatter
有了五线谱,该来点音符了,StaveNote 类抽象音符,使用其的方法如下:
1 |
|
音符的构造器接受一个复杂对象,常用的或许有这些配置:keys,duration,clef,auto_stem。
- keys 即音符名集合,如 C/4 代表 C4,E/5 代表 E5;形如 G#/4 这样带上变音符的音符也是合法的,但似乎没有效果,而变音号需要使用 Modifier 去表示;key 会决定音符的位置,即使是休止符也不例外;全休止符的位置为 D/5,二分休止符为 B/4,四分休止符为 B/4。
- duration 即音符时值,1 表示全音符,2 和 h(half)表示二分音符,4 和 q 表示 4 分音符,8,16,32 表示对应分数音符,加上 r 表示休止符,加上 d 表示附点,比如 2rdd 表示二分复附点休止符(附点会影响(声部的)时值的计算,但渲染上没有影响)。
- clef 同 Stave 的 clef,影响音符位置,默认 clef 是 treble。
- auto_stem 是布尔值,表示是否自动调整符干朝向,默认关闭。
这里,输出音符使用了 Formatter 这个类的静态方法,其中参数包括 context,stave,以及要输出的 Note;能够猜测,需要 context 的原因是需要利用其方法去绘图,需要 stave 的原因是因为需要知道五线谱的位置,这样才能计算出要绘制的音符的位置。
Modifier
想要让 vexflow 给音符渲染升降号或附点,需要使用所谓的 Modifier,Modifier 应用在 StateNote 上,具体使用见代码和注释。
1 |
|
虽然并没有学到多少东西,但我发现目前的进度好像已经能满足我的需要了!这个框架显然是专注渲染的,至于渲染的东西是否正确或合法,它并不怎么关心(但至少使用声部Voice的时候它会保证时值正确);将来若有需要的话再进一步学习(这时候估计是去专注相关样式),现在该对其进行封装了。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议 ,转载请注明出处!