forked from ringw/vexflow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfrethandfinger.js
166 lines (144 loc) · 5.34 KB
/
frethandfinger.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// VexFlow - Music Engraving for HTML5
// Copyright Mohit Muthanna 2010
// Author Larry Kuhns 2013
// Class to draws string numbers into the notation.
/**
* @constructor
*/
Vex.Flow.FretHandFinger = (function() {
function FretHandFinger(number) {
if (arguments.length > 0) this.init(number);
}
FretHandFinger.CATEGORY = "frethandfinger";
var Modifier = Vex.Flow.Modifier;
// Arrange fingerings inside a ModifierContext.
FretHandFinger.format = function(nums, state) {
var left_shift = state.left_shift;
var right_shift = state.right_shift;
var num_spacing = 1;
if (!nums || nums.length === 0) return false;
var nums_list = [];
var prev_note = null;
var shift_left = 0;
var shift_right = 0;
var i, num, note, pos, props_tmp;
for (i = 0; i < nums.length; ++i) {
num = nums[i];
note = num.getNote();
pos = num.getPosition();
var props = note.getKeyProps()[num.getIndex()];
if (note != prev_note) {
for (var n = 0; n < note.keys.length; ++n) {
props_tmp = note.getKeyProps()[n];
if (left_shift === 0)
shift_left = (props_tmp.displaced ? note.getExtraLeftPx() : shift_left);
if (right_shift === 0)
shift_right = (props_tmp.displaced ? note.getExtraRightPx() : shift_right);
}
prev_note = note;
}
nums_list.push({ line: props.line, pos: pos, shiftL: shift_left, shiftR: shift_right, note: note, num: num });
}
// Sort fingernumbers by line number.
nums_list.sort(function(a, b) { return (b.line - a.line); });
var num_shiftL = 0;
var num_shiftR = 0;
var x_widthL = 0;
var x_widthR = 0;
var last_line = null;
var last_note = null;
for (i = 0; i < nums_list.length; ++i) {
var num_shift = 0;
note = nums_list[i].note;
pos = nums_list[i].pos;
num = nums_list[i].num;
var line = nums_list[i].line;
var shiftL = nums_list[i].shiftL;
var shiftR = nums_list[i].shiftR;
// Reset the position of the string number every line.
if (line != last_line || note != last_note) {
num_shiftL = left_shift + shiftL;
num_shiftR = right_shift + shiftR;
}
var num_width = num.getWidth() + num_spacing;
if (pos == Vex.Flow.Modifier.Position.LEFT) {
num.setXShift(left_shift + num_shiftL);
num_shift = left_shift + num_width; // spacing
x_widthL = (num_shift > x_widthL) ? num_shift : x_widthL;
} else if (pos == Vex.Flow.Modifier.Position.RIGHT) {
num.setXShift(num_shiftR);
num_shift = shift_right + num_width; // spacing
x_widthR = (num_shift > x_widthR) ? num_shift : x_widthR;
}
last_line = line;
last_note = note;
}
state.left_shift += x_widthL;
state.right_shift += x_widthR;
};
Vex.Inherit(FretHandFinger, Modifier, {
init: function(number) {
var superclass = Vex.Flow.FretHandFinger.superclass;
superclass.init.call(this);
this.note = null;
this.index = null;
this.finger = number;
this.width = 7;
this.position = Modifier.Position.LEFT; // Default position above stem or note head
this.x_shift = 0;
this.y_shift = 0;
this.x_offset = 0; // Horizontal offset from default
this.y_offset = 0; // Vertical offset from default
this.font = {
family: "sans-serif",
size: 9,
weight: "bold"
};
},
getNote: function() { return this.note; },
setNote: function(note) { this.note = note; return this; },
getIndex: function() { return this.index; },
setIndex: function(index) { this.index = index; return this; },
getPosition: function() { return this.position; },
setPosition: function(position) {
if (position >= Modifier.Position.LEFT &&
position <= Modifier.Position.BELOW)
this.position = position;
return this;
},
setFretHandFinger: function(number) { this.finger = number; return this; },
setOffsetX: function(x) { this.x_offset = x; return this; },
setOffsetY: function(y) { this.y_offset = y; return this; },
draw: function() {
if (!this.context) throw new Vex.RERR("NoContext",
"Can't draw string number without a context.");
if (!(this.note && (this.index != null))) throw new Vex.RERR("NoAttachedNote",
"Can't draw string number without a note and index.");
var ctx = this.context;
var start = this.note.getModifierStartXY(this.position, this.index);
var dot_x = (start.x + this.x_shift + this.x_offset);
var dot_y = start.y + this.y_shift + this.y_offset + 5;
switch (this.position) {
case Modifier.Position.ABOVE:
dot_x -= 4;
dot_y -= 12;
break;
case Modifier.Position.BELOW:
dot_x -= 2;
dot_y += 10;
break;
case Modifier.Position.LEFT:
dot_x -= this.width;
break;
case Modifier.Position.RIGHT:
dot_x += 1;
break;
}
ctx.save();
ctx.setFont(this.font.family, this.font.size, this.font.weight);
ctx.fillText("" + this.finger, dot_x, dot_y);
ctx.restore();
}
});
return FretHandFinger;
}());