vector-score 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -29
- package/dist/classes/GuitarChord.d.ts +3 -1
- package/dist/classes/SVGRenderer.d.ts +4 -0
- package/dist/constants.d.ts +6 -6
- package/dist/vector-score.js +342 -315
- package/dist/vector-score.umd.cjs +1 -1
- package/package.json +1 -1
package/dist/vector-score.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const R = {
|
|
2
2
|
treble: {
|
|
3
3
|
staffType: "treble",
|
|
4
4
|
paddingTop: 13,
|
|
@@ -37,10 +37,10 @@ const S = {
|
|
|
37
37
|
q: 1,
|
|
38
38
|
e: 0.5,
|
|
39
39
|
s: 0.25
|
|
40
|
-
},
|
|
40
|
+
}, at = 6, ct = 5, _ = 22, T = 30, u = 10, g = 6, ht = 4, lt = u * 2, M = 51, dt = 12, ft = 4, $ = 1, P = 4, k = 1, W = g * 2 + P + 4, rt = 16, S = 12, Z = rt, ut = 2, V = 8, Et = 40, nt = {
|
|
41
41
|
sharp: ["F", "C", "G", "D", "A", "E", "B"],
|
|
42
42
|
flat: ["B", "E", "A", "D", "G", "C", "F"]
|
|
43
|
-
},
|
|
43
|
+
}, q = {
|
|
44
44
|
C: { type: "sharp", count: 0 },
|
|
45
45
|
G: { type: "sharp", count: 1 },
|
|
46
46
|
D: { type: "sharp", count: 2 },
|
|
@@ -54,7 +54,7 @@ const S = {
|
|
|
54
54
|
Ab: { type: "flat", count: 4 },
|
|
55
55
|
Db: { type: "flat", count: 5 },
|
|
56
56
|
Gb: { type: "flat", count: 6 }
|
|
57
|
-
},
|
|
57
|
+
}, x = {
|
|
58
58
|
treble: {
|
|
59
59
|
sharp: [5, 5, 5, 5, 4, 5, 4],
|
|
60
60
|
// F5 C5 G5 D5 A4 E5 B4
|
|
@@ -75,22 +75,22 @@ const S = {
|
|
|
75
75
|
},
|
|
76
76
|
grand: { sharp: [], flat: [] }
|
|
77
77
|
};
|
|
78
|
-
function
|
|
79
|
-
const e =
|
|
80
|
-
if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(
|
|
78
|
+
function gt(h) {
|
|
79
|
+
const e = q[h];
|
|
80
|
+
if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(q).join(", ")}`);
|
|
81
81
|
return e;
|
|
82
82
|
}
|
|
83
|
-
function
|
|
84
|
-
const r =
|
|
83
|
+
function At(h, e, t, s) {
|
|
84
|
+
const r = gt(t);
|
|
85
85
|
if (r.count === 0) return 0;
|
|
86
|
-
const
|
|
86
|
+
const n = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", o = h.getLayerByName("staff");
|
|
87
87
|
return e.getKeySignatureYPositions(r.type, r.count).forEach((a) => {
|
|
88
88
|
a.forEach((c, l) => {
|
|
89
|
-
h.drawGlyph(
|
|
89
|
+
h.drawGlyph(n, o, { xOffset: s + l * V, yOffset: c });
|
|
90
90
|
});
|
|
91
|
-
}), r.count *
|
|
91
|
+
}), r.count * V;
|
|
92
92
|
}
|
|
93
|
-
const
|
|
93
|
+
const pt = {
|
|
94
94
|
CLEF_TREBLE: {
|
|
95
95
|
path: "m150 273 10 58c2 7 2 7 12 7 59 0 96 46 96 97 0 45-26 79-67 95-5 2-6 2-5 7 4 25 12 63 12 85 0 68-52 80-79 80-61 0-76-39-76-65 0-25 16-46 43-46 24 0 38 19 38 41 0 23-14 34-27 38-9 2-13 4-13 6 0 6 11 12 32 12 24 0 64-7 64-66 0-19-6-54-11-81-1-5-1-4-6-3l-27 2C48 540 0 474 0 404c0-80 61-138 119-185 5-4 4-5 3-10-2-16-5-42-5-65 0-42 9-92 39-125 8-9 20-19 26-19 4 0 15 11 21 20 16 24 26 58 26 93 0 61-33 112-76 153-3 2-3 2-3 7Zm38-211c-24 0-53 38-53 101l2 37c1 5 3 5 5 3 32-28 70-64 70-108 0-22-11-33-24-33Zm-44 272-8-51c-1-4-2-5-6-1-18 15-37 30-61 56-33 38-37 70-37 93 0 56 45 95 115 95l23-2c6-2 6-2 5-6l-20-119c-1-5-1-5-8-3-24 6-40 24-40 46 0 19 12 36 29 43 3 1 6 3 6 5 0 3-2 5-5 5l-11-3c-27-9-46-34-46-70 0-34 23-66 58-78 8-2 8-2 6-10Zm28 64 20 114c0 5 1 5 6 2 22-11 38-31 38-56 0-36-27-63-60-66-4 0-5 1-4 6Z",
|
|
96
96
|
xOffset: 0,
|
|
@@ -186,26 +186,26 @@ const Et = {
|
|
|
186
186
|
xOffset: 0,
|
|
187
187
|
yOffset: 0
|
|
188
188
|
}
|
|
189
|
-
},
|
|
190
|
-
function
|
|
191
|
-
const e = h.match(
|
|
189
|
+
}, It = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, _t = /^[whqeWHQE]$/, X = ["C", "D", "E", "F", "G", "A", "B"];
|
|
190
|
+
function U(h) {
|
|
191
|
+
const e = h.match(It);
|
|
192
192
|
if (!e || !e.groups)
|
|
193
193
|
throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
|
|
194
|
-
let { name: t, accidental: s, octave: r, duration:
|
|
195
|
-
t = t.toUpperCase(),
|
|
196
|
-
const
|
|
194
|
+
let { name: t, accidental: s, octave: r, duration: n } = e.groups;
|
|
195
|
+
t = t.toUpperCase(), n = n.toLowerCase(), n || (n = "w");
|
|
196
|
+
const o = {
|
|
197
197
|
name: t,
|
|
198
198
|
octave: parseInt(r),
|
|
199
|
-
duration:
|
|
199
|
+
duration: n
|
|
200
200
|
};
|
|
201
|
-
return s && (
|
|
201
|
+
return s && (o.accidental = s), o;
|
|
202
202
|
}
|
|
203
|
-
function
|
|
204
|
-
const e = h.match(
|
|
203
|
+
function b(h) {
|
|
204
|
+
const e = h.match(_t);
|
|
205
205
|
if (!e) throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);
|
|
206
206
|
return e[0].toString().toLowerCase();
|
|
207
207
|
}
|
|
208
|
-
function
|
|
208
|
+
function Y(h) {
|
|
209
209
|
let e;
|
|
210
210
|
switch (h) {
|
|
211
211
|
case "treble":
|
|
@@ -221,22 +221,22 @@ function x(h) {
|
|
|
221
221
|
if (!e) throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);
|
|
222
222
|
return e;
|
|
223
223
|
}
|
|
224
|
-
function
|
|
225
|
-
let e =
|
|
224
|
+
function z(h) {
|
|
225
|
+
let e = X.indexOf(h.name);
|
|
226
226
|
return e += h.octave * 12, e;
|
|
227
227
|
}
|
|
228
|
-
function
|
|
229
|
-
return
|
|
228
|
+
function N(h, e) {
|
|
229
|
+
return X.indexOf(h.name) - X.indexOf(e.name) + (h.octave - e.octave) * 7;
|
|
230
230
|
}
|
|
231
|
-
const
|
|
232
|
-
class
|
|
231
|
+
const G = 48, j = 40 + 30 / 2, K = 20, Q = 90;
|
|
232
|
+
class ot {
|
|
233
233
|
params;
|
|
234
234
|
rendererRef;
|
|
235
235
|
width = 0;
|
|
236
236
|
trebleStaffHeight = 0;
|
|
237
237
|
constructor(e, t) {
|
|
238
238
|
this.rendererRef = e;
|
|
239
|
-
const s =
|
|
239
|
+
const s = R[t];
|
|
240
240
|
if (!s) throw new Error(`Staff type ${t} is not supported`);
|
|
241
241
|
this.params = s;
|
|
242
242
|
}
|
|
@@ -251,59 +251,59 @@ class tt {
|
|
|
251
251
|
const t = this.rendererRef.getLayerByName("staff");
|
|
252
252
|
let s = this.drawStaffLines(0, t), r = this.drawStaffLines(s + 30, t);
|
|
253
253
|
this.rendererRef.drawLine(0, 0, 0, r, t), this.rendererRef.drawLine(this.width, 0, this.width, r, t), this.trebleStaffHeight = s;
|
|
254
|
-
let
|
|
255
|
-
const i =
|
|
256
|
-
this.rendererRef.drawGlyph(i, t), this.rendererRef.drawGlyph(a, t, { yOffset: s + 30 }),
|
|
254
|
+
let n = r, o = 1;
|
|
255
|
+
const i = Y("treble"), a = Y("bass");
|
|
256
|
+
this.rendererRef.drawGlyph(i, t), this.rendererRef.drawGlyph(a, t, { yOffset: s + 30 }), n += this.params.paddingBottom + 1, o += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(n), this.rendererRef.addTotalRootSvgYOffset(o);
|
|
257
257
|
};
|
|
258
258
|
shouldNoteFlip(e) {
|
|
259
|
-
const t = Math.abs(e -
|
|
260
|
-
return e ===
|
|
259
|
+
const t = Math.abs(e - Q), s = Math.abs(e - K);
|
|
260
|
+
return e === j ? !1 : t <= s ? !(e >= Q) : e <= K;
|
|
261
261
|
}
|
|
262
262
|
getLedgerLinesX(e, t) {
|
|
263
|
-
const s = [], r =
|
|
264
|
-
let
|
|
265
|
-
if (r ===
|
|
266
|
-
return s.push({ x1: -2, x2:
|
|
263
|
+
const s = [], r = z(e);
|
|
264
|
+
let n = e.duration === "w" ? 17 : 12.5;
|
|
265
|
+
if (r === G)
|
|
266
|
+
return s.push({ x1: -2, x2: n, yPos: 0 }), s;
|
|
267
267
|
if (t < this.params.topLineYPos) {
|
|
268
|
-
let
|
|
269
|
-
for (;
|
|
268
|
+
let o = this.params.topLineYPos - 10;
|
|
269
|
+
for (; o >= t; )
|
|
270
270
|
s.push({
|
|
271
271
|
x1: -2,
|
|
272
|
-
x2:
|
|
273
|
-
yPos:
|
|
274
|
-
}),
|
|
272
|
+
x2: n,
|
|
273
|
+
yPos: o - t
|
|
274
|
+
}), o -= 10;
|
|
275
275
|
} else if (t > this.params.bottomLineYPos) {
|
|
276
|
-
let
|
|
277
|
-
for (;
|
|
276
|
+
let o = this.params.bottomLineYPos + 10;
|
|
277
|
+
for (; o <= t; )
|
|
278
278
|
s.push({
|
|
279
279
|
x1: -2,
|
|
280
|
-
x2:
|
|
281
|
-
yPos:
|
|
282
|
-
}),
|
|
280
|
+
x2: n,
|
|
281
|
+
yPos: o - t
|
|
282
|
+
}), o += 10;
|
|
283
283
|
}
|
|
284
284
|
return s;
|
|
285
285
|
}
|
|
286
286
|
calculateNoteYPos = (e) => {
|
|
287
|
-
let s =
|
|
288
|
-
const r =
|
|
289
|
-
return r <
|
|
287
|
+
let s = N(this.params.topLineNote, e) * (10 / 2);
|
|
288
|
+
const r = z(e);
|
|
289
|
+
return r < G ? s += 10 : r === G && (s = j), s;
|
|
290
290
|
};
|
|
291
291
|
getKeySignatureYPositions(e, t) {
|
|
292
|
-
const s =
|
|
293
|
-
(a, c) =>
|
|
292
|
+
const s = nt[e].slice(0, t), r = x.treble[e], n = x.bass[e], o = s.map(
|
|
293
|
+
(a, c) => N(R.treble.topLineNote, { name: a, octave: r[c] }) * (10 / 2)
|
|
294
294
|
), i = s.map(
|
|
295
|
-
(a, c) =>
|
|
295
|
+
(a, c) => N(R.bass.topLineNote, { name: a, octave: n[c] }) * (10 / 2) + this.trebleStaffHeight + 30
|
|
296
296
|
);
|
|
297
|
-
return [
|
|
297
|
+
return [o, i];
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
-
const
|
|
301
|
-
class
|
|
300
|
+
const Tt = 20;
|
|
301
|
+
class m {
|
|
302
302
|
params;
|
|
303
303
|
rendererRef;
|
|
304
304
|
constructor(e, t) {
|
|
305
305
|
this.rendererRef = e;
|
|
306
|
-
const s =
|
|
306
|
+
const s = R[t];
|
|
307
307
|
if (!s) throw new Error(`Staff type ${t} is not supported`);
|
|
308
308
|
this.params = s;
|
|
309
309
|
}
|
|
@@ -313,44 +313,44 @@ class _ {
|
|
|
313
313
|
for (let i = 0; i < 5; i++)
|
|
314
314
|
this.rendererRef.drawLine(0, s, e, s, t), s += 10;
|
|
315
315
|
this.rendererRef.drawLine(0, 0, 0, s - 10, t), this.rendererRef.drawLine(e, 0, e, s - 10, t);
|
|
316
|
-
let r = s - 10 + 1,
|
|
317
|
-
const
|
|
318
|
-
this.rendererRef.drawGlyph(
|
|
316
|
+
let r = s - 10 + 1, n = 1;
|
|
317
|
+
const o = Y(this.params.staffType);
|
|
318
|
+
this.rendererRef.drawGlyph(o, t), r += this.params.paddingTop + this.params.paddingBottom, n += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(r), this.rendererRef.addTotalRootSvgYOffset(n);
|
|
319
319
|
};
|
|
320
320
|
shouldNoteFlip(e) {
|
|
321
|
-
return e <=
|
|
321
|
+
return e <= Tt;
|
|
322
322
|
}
|
|
323
323
|
getLedgerLinesX(e, t) {
|
|
324
324
|
const s = [];
|
|
325
325
|
let r = e.duration === "w" ? 17 : 12.5;
|
|
326
326
|
if (t < this.params.topLineYPos) {
|
|
327
|
-
let
|
|
328
|
-
for (;
|
|
327
|
+
let n = this.params.topLineYPos - 10;
|
|
328
|
+
for (; n >= t; )
|
|
329
329
|
s.push({
|
|
330
330
|
x1: -2,
|
|
331
331
|
x2: r,
|
|
332
|
-
yPos:
|
|
333
|
-
}),
|
|
332
|
+
yPos: n - t
|
|
333
|
+
}), n -= 10;
|
|
334
334
|
} else if (t > this.params.bottomLineYPos) {
|
|
335
|
-
let
|
|
336
|
-
for (;
|
|
335
|
+
let n = this.params.bottomLineYPos + 10;
|
|
336
|
+
for (; n <= t; )
|
|
337
337
|
s.push({
|
|
338
338
|
x1: -2,
|
|
339
339
|
x2: r,
|
|
340
|
-
yPos:
|
|
341
|
-
}),
|
|
340
|
+
yPos: n - t
|
|
341
|
+
}), n += 10;
|
|
342
342
|
}
|
|
343
343
|
return s;
|
|
344
344
|
}
|
|
345
|
-
calculateNoteYPos = (e) =>
|
|
345
|
+
calculateNoteYPos = (e) => N(this.params.topLineNote, e) * (10 / 2);
|
|
346
346
|
getKeySignatureYPositions(e, t) {
|
|
347
|
-
const s =
|
|
347
|
+
const s = nt[e].slice(0, t), r = x[this.params.staffType][e];
|
|
348
348
|
return [s.map(
|
|
349
|
-
(
|
|
349
|
+
(o, i) => this.calculateNoteYPos({ name: o, octave: r[i] })
|
|
350
350
|
)];
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
|
-
class
|
|
353
|
+
class it {
|
|
354
354
|
svgRendererInstance;
|
|
355
355
|
strategyInstance;
|
|
356
356
|
constructor(e, t) {
|
|
@@ -361,10 +361,10 @@ class et {
|
|
|
361
361
|
}
|
|
362
362
|
chordOffsetConsecutiveAccidentals(e) {
|
|
363
363
|
let t = 0, s = 0, r = 0;
|
|
364
|
-
for (let
|
|
365
|
-
const
|
|
366
|
-
if (
|
|
367
|
-
const a = Array.from(
|
|
364
|
+
for (let n = 0; n < e.length; n++) {
|
|
365
|
+
const o = e[n];
|
|
366
|
+
if (o.noteObj.accidental && r < 3 ? (t += -8, s = Math.min(s, t), r++) : o.noteObj.accidental && r <= 3 ? (t = -8, r = 1) : (t = 0, r = 0), t !== 0) {
|
|
367
|
+
const a = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
|
|
368
368
|
if (!a) continue;
|
|
369
369
|
a.setAttribute("transform", `translate(${t + 8}, 0)`);
|
|
370
370
|
}
|
|
@@ -374,10 +374,10 @@ class et {
|
|
|
374
374
|
chordOffsetCloseNotes(e) {
|
|
375
375
|
let t = e[0], s = 0;
|
|
376
376
|
for (let r = 1; r < e.length; r++) {
|
|
377
|
-
const
|
|
378
|
-
if (-
|
|
379
|
-
s = 28 / 2,
|
|
380
|
-
const a = Array.from(
|
|
377
|
+
const n = e[r];
|
|
378
|
+
if (-N(t.noteObj, n.noteObj) === 1) {
|
|
379
|
+
s = 28 / 2, n.noteGroup.setAttribute("transform", `translate(${s}, ${n.noteYPos})`);
|
|
380
|
+
const a = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
|
|
381
381
|
if (a) {
|
|
382
382
|
const c = a.getAttribute("transform")?.match(/([-]?\d+)/), l = c && c[0];
|
|
383
383
|
let d = -s;
|
|
@@ -386,46 +386,46 @@ class et {
|
|
|
386
386
|
r++, t = e[r];
|
|
387
387
|
continue;
|
|
388
388
|
}
|
|
389
|
-
t =
|
|
389
|
+
t = n;
|
|
390
390
|
}
|
|
391
391
|
return s;
|
|
392
392
|
}
|
|
393
393
|
// Handles drawing the glyphs to internal group, applies the xPositioning to note Cursor X
|
|
394
394
|
renderNote(e) {
|
|
395
|
-
const t = this.svgRendererInstance.createGroup("note"), s =
|
|
395
|
+
const t = this.svgRendererInstance.createGroup("note"), s = U(e), r = this.strategyInstance.calculateNoteYPos({
|
|
396
396
|
name: s.name,
|
|
397
397
|
octave: s.octave
|
|
398
398
|
});
|
|
399
|
-
let
|
|
399
|
+
let n = this.strategyInstance.shouldNoteFlip(r);
|
|
400
400
|
switch (s.duration) {
|
|
401
401
|
case "h":
|
|
402
|
-
this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t,
|
|
402
|
+
this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, n);
|
|
403
403
|
break;
|
|
404
404
|
case "q":
|
|
405
|
-
this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t,
|
|
405
|
+
this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, n);
|
|
406
406
|
break;
|
|
407
407
|
case "e":
|
|
408
|
-
|
|
408
|
+
n ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
|
|
409
409
|
break;
|
|
410
410
|
default:
|
|
411
411
|
this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE", t);
|
|
412
412
|
}
|
|
413
|
-
let
|
|
413
|
+
let o = 0;
|
|
414
414
|
switch (s.accidental) {
|
|
415
415
|
case "#":
|
|
416
|
-
this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t),
|
|
416
|
+
this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), o -= -8;
|
|
417
417
|
break;
|
|
418
418
|
case "b":
|
|
419
|
-
this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t),
|
|
419
|
+
this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), o -= -8;
|
|
420
420
|
break;
|
|
421
421
|
case "n":
|
|
422
|
-
this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t),
|
|
422
|
+
this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), o -= -8;
|
|
423
423
|
break;
|
|
424
424
|
case "##":
|
|
425
|
-
this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t),
|
|
425
|
+
this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), o -= -10;
|
|
426
426
|
break;
|
|
427
427
|
case "bb":
|
|
428
|
-
this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t),
|
|
428
|
+
this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), o -= -14;
|
|
429
429
|
break;
|
|
430
430
|
}
|
|
431
431
|
return this.strategyInstance.getLedgerLinesX(s, r).forEach((a) => {
|
|
@@ -434,14 +434,14 @@ class et {
|
|
|
434
434
|
noteGroup: t,
|
|
435
435
|
noteObj: s,
|
|
436
436
|
noteYPos: r,
|
|
437
|
-
accidentalOffset:
|
|
437
|
+
accidentalOffset: o,
|
|
438
438
|
cursorOffset: 0
|
|
439
439
|
};
|
|
440
440
|
}
|
|
441
441
|
renderChord(e) {
|
|
442
442
|
const t = this.svgRendererInstance.createGroup("chord"), s = [];
|
|
443
|
-
for (const
|
|
444
|
-
const i = this.renderNote(
|
|
443
|
+
for (const o of e) {
|
|
444
|
+
const i = this.renderNote(o);
|
|
445
445
|
i.noteGroup.setAttribute("transform", `translate(0, ${i.noteYPos})`), t.appendChild(i.noteGroup), s.push({
|
|
446
446
|
noteGroup: i.noteGroup,
|
|
447
447
|
noteObj: i.noteObj,
|
|
@@ -450,18 +450,18 @@ class et {
|
|
|
450
450
|
accidentalOffset: 0
|
|
451
451
|
});
|
|
452
452
|
}
|
|
453
|
-
const r = this.chordOffsetConsecutiveAccidentals(s),
|
|
453
|
+
const r = this.chordOffsetConsecutiveAccidentals(s), n = this.chordOffsetCloseNotes(s);
|
|
454
454
|
return {
|
|
455
455
|
noteGroup: t,
|
|
456
456
|
noteObj: s[0].noteObj,
|
|
457
457
|
noteYPos: 0,
|
|
458
458
|
accidentalOffset: r,
|
|
459
|
-
cursorOffset:
|
|
459
|
+
cursorOffset: n
|
|
460
460
|
};
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
|
-
const
|
|
464
|
-
class
|
|
463
|
+
const A = "http://www.w3.org/2000/svg", mt = 0.1, v = 1200;
|
|
464
|
+
class w {
|
|
465
465
|
rootElementRef;
|
|
466
466
|
svgElementRef;
|
|
467
467
|
// Layers
|
|
@@ -479,18 +479,21 @@ class L {
|
|
|
479
479
|
// from get rootSvgElement().
|
|
480
480
|
// HEIGHT and YOfsset should be set externally, values are calculated internally.
|
|
481
481
|
constructor(e, t) {
|
|
482
|
-
this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.width >
|
|
482
|
+
this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.width > v && (this.width = v, console.warn(`Width provided for the staff ${this.width} exceeds the limit ${v}. Please use this value to fix positioning issues.`)), this.svgElementRef = document.createElementNS(A, "svg"), this.svgElementRef.classList.add("vs-svg-renderer-root"), this.svgElementRef.style.maxWidth = "100%", this.svgElementRef.style.height = "auto", this.svgElementRef.style.display = "block", this.svgElementRef.setAttribute("color", t.staffColor), this.svgElementRef.style.backgroundColor = t.staffBackgroundColor, this.makeGlyphDefs(t.useGlyphs), this.parentGroupContainer = this.createGroup("svg-renderer-parent"), this.svgElementRef.appendChild(this.parentGroupContainer), this.musicStaffLayer = this.createGroup("music-staff-layer"), this.musicNotesLayer = this.createGroup("music-notes-layer"), this.musicUILayer = this.createGroup("music-ui-layer"), this.parentGroupContainer.appendChild(this.musicStaffLayer), this.parentGroupContainer.appendChild(this.musicNotesLayer), this.parentGroupContainer.appendChild(this.musicUILayer);
|
|
483
483
|
}
|
|
484
484
|
// Creates SVG defs for all glyphs in GLYPH_ENTRIES, applies global scale and offsets, appends to root SVG
|
|
485
485
|
makeGlyphDefs(e) {
|
|
486
|
-
const t = document.createElementNS(
|
|
487
|
-
Object.entries(
|
|
488
|
-
const
|
|
489
|
-
|
|
486
|
+
const t = document.createElementNS(A, "defs");
|
|
487
|
+
Object.entries(pt).filter(([r]) => e.includes(r)).forEach(([r, n]) => {
|
|
488
|
+
const o = document.createElementNS(A, "path");
|
|
489
|
+
o.setAttribute("id", `glyph-${r}`), o.setAttribute("d", n.path), o.setAttribute("fill", "currentColor"), o.setAttribute("transform", `translate(${n.xOffset}, ${n.yOffset}) scale(${mt})`), t.appendChild(o);
|
|
490
490
|
}), this.rootSvgElement.appendChild(t);
|
|
491
491
|
}
|
|
492
|
+
addNamespacedClassesToElement(e, t) {
|
|
493
|
+
[e].flat().forEach((r) => t.classList.add(`vs-${r}`));
|
|
494
|
+
}
|
|
492
495
|
createGroup(e) {
|
|
493
|
-
const t = document.createElementNS(
|
|
496
|
+
const t = document.createElementNS(A, "g");
|
|
494
497
|
return e && t.classList.add(`vs-${e}`), t;
|
|
495
498
|
}
|
|
496
499
|
commitElementsToDOM(e, t = this.rootElementRef) {
|
|
@@ -533,13 +536,13 @@ class L {
|
|
|
533
536
|
return this.parentGroupContainer;
|
|
534
537
|
}
|
|
535
538
|
// Drawing Methods
|
|
536
|
-
drawLine(e, t, s, r,
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
+
drawLine(e, t, s, r, n) {
|
|
540
|
+
const o = document.createElementNS(A, "line");
|
|
541
|
+
o.setAttribute("x1", e.toString()), o.setAttribute("y1", t.toString()), o.setAttribute("x2", s.toString()), o.setAttribute("y2", r.toString()), o.setAttribute("stroke", "currentColor"), o.setAttribute("stroke-width", "1"), n.appendChild(o);
|
|
539
542
|
}
|
|
540
543
|
drawRect(e, t, s, r) {
|
|
541
|
-
const
|
|
542
|
-
return
|
|
544
|
+
const n = document.createElementNS(A, "rect");
|
|
545
|
+
return n.setAttribute("width", e.toString()), n.setAttribute("height", t.toString()), n.setAttribute("x", (r?.x ?? 0).toString()), n.setAttribute("y", (r?.y ?? 0).toString()), r?.fill ? n.setAttribute("fill", r.fill) : n.setAttribute("fill", "currentColor"), r?.rx && n.setAttribute("rx", r.rx.toString()), r?.classes && this.addNamespacedClassesToElement(r.classes, n), s.appendChild(n), n;
|
|
543
546
|
}
|
|
544
547
|
drawGlyph(e, t, s) {
|
|
545
548
|
s = {
|
|
@@ -547,22 +550,22 @@ class L {
|
|
|
547
550
|
yOffset: 0,
|
|
548
551
|
...s
|
|
549
552
|
};
|
|
550
|
-
const r = document.createElementNS(
|
|
553
|
+
const r = document.createElementNS(A, "use");
|
|
551
554
|
r.setAttribute("href", `#glyph-${e}`), (s.xOffset || s.yOffset) && r.setAttribute("transform", `translate(${s.xOffset}, ${s.yOffset})`), t.appendChild(r);
|
|
552
555
|
}
|
|
553
|
-
drawCircle(e, t, s, r,
|
|
554
|
-
const
|
|
555
|
-
return
|
|
556
|
+
drawCircle(e, t, s, r, n) {
|
|
557
|
+
const o = document.createElementNS(A, "circle");
|
|
558
|
+
return o.setAttribute("cx", e.toString()), o.setAttribute("cy", t.toString()), o.setAttribute("r", s.toString()), n?.filled === !1 ? (o.setAttribute("fill", "none"), o.setAttribute("stroke", "currentColor"), o.setAttribute("stroke-width", (n?.strokeWidth ?? 1.5).toString())) : o.setAttribute("fill", n?.fill ?? "currentColor"), n?.classes && this.addNamespacedClassesToElement(n.classes, o), r.appendChild(o), o;
|
|
556
559
|
}
|
|
557
|
-
drawText(e, t, s, r,
|
|
558
|
-
const
|
|
559
|
-
return
|
|
560
|
+
drawText(e, t, s, r, n) {
|
|
561
|
+
const o = document.createElementNS(A, "text");
|
|
562
|
+
return o.setAttribute("x", t.toString()), o.setAttribute("y", s.toString()), o.setAttribute("text-anchor", n?.anchor ?? "middle"), o.setAttribute("fill", n?.fill ?? "currentColor"), n?.fontSize && o.setAttribute("font-size", n.fontSize + "px"), n?.fontWeight && o.setAttribute("font-weight", n.fontWeight), n?.classes && this.addNamespacedClassesToElement(n.classes, o), o.textContent = e, r.appendChild(o), o;
|
|
560
563
|
}
|
|
561
564
|
destroy() {
|
|
562
565
|
this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
|
|
563
566
|
}
|
|
564
567
|
}
|
|
565
|
-
const
|
|
568
|
+
const Ct = [
|
|
566
569
|
"CLEF_TREBLE",
|
|
567
570
|
"CLEF_BASS",
|
|
568
571
|
"CLEF_ALTO",
|
|
@@ -577,7 +580,7 @@ const It = [
|
|
|
577
580
|
"ACCIDENTAL_DOUBLE_SHARP",
|
|
578
581
|
"ACCIDENTAL_DOUBLE_FLAT"
|
|
579
582
|
];
|
|
580
|
-
class
|
|
583
|
+
class bt {
|
|
581
584
|
svgRendererInstance;
|
|
582
585
|
strategyInstance;
|
|
583
586
|
noteRendererInstance;
|
|
@@ -602,44 +605,44 @@ class Rt {
|
|
|
602
605
|
staffColor: "black",
|
|
603
606
|
staffBackgroundColor: "transparent",
|
|
604
607
|
...t
|
|
605
|
-
}, this.svgRendererInstance = new
|
|
608
|
+
}, this.svgRendererInstance = new w(e, {
|
|
606
609
|
width: this.options.width,
|
|
607
610
|
height: 100,
|
|
608
611
|
scale: this.options.scale,
|
|
609
612
|
staffColor: this.options.staffColor,
|
|
610
613
|
staffBackgroundColor: this.options.staffBackgroundColor,
|
|
611
|
-
useGlyphs:
|
|
614
|
+
useGlyphs: Ct
|
|
612
615
|
});
|
|
613
616
|
const s = this.svgRendererInstance.rootSvgElement;
|
|
614
617
|
switch (this.options.staffType) {
|
|
615
618
|
case "grand":
|
|
616
|
-
this.strategyInstance = new
|
|
619
|
+
this.strategyInstance = new ot(this.svgRendererInstance, "grand");
|
|
617
620
|
break;
|
|
618
621
|
case "bass":
|
|
619
|
-
this.strategyInstance = new
|
|
622
|
+
this.strategyInstance = new m(this.svgRendererInstance, "bass");
|
|
620
623
|
break;
|
|
621
624
|
case "treble":
|
|
622
|
-
this.strategyInstance = new
|
|
625
|
+
this.strategyInstance = new m(this.svgRendererInstance, "treble");
|
|
623
626
|
break;
|
|
624
627
|
case "alto":
|
|
625
|
-
this.strategyInstance = new
|
|
628
|
+
this.strategyInstance = new m(this.svgRendererInstance, "alto");
|
|
626
629
|
break;
|
|
627
630
|
default:
|
|
628
631
|
throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
|
|
629
632
|
}
|
|
630
|
-
if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new
|
|
631
|
-
const
|
|
632
|
-
this.svgRendererInstance.addTotalRootSvgYOffset(
|
|
633
|
+
if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
|
|
634
|
+
const n = this.options.spaceAbove * 10;
|
|
635
|
+
this.svgRendererInstance.addTotalRootSvgYOffset(n);
|
|
633
636
|
}
|
|
634
637
|
if (this.options.spaceBelow) {
|
|
635
|
-
let
|
|
636
|
-
this.options.staffType === "grand" && (
|
|
638
|
+
let n = this.options.spaceBelow * 10;
|
|
639
|
+
this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
|
|
637
640
|
}
|
|
638
641
|
let r = 0;
|
|
639
642
|
this.options.keySignature && (r = this.createKeySignature(this.options.keySignature)), this.noteStartX = 38 + this.options.noteStartX + r, this.svgRendererInstance.getLayerByName("notes").setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
|
|
640
643
|
}
|
|
641
644
|
createKeySignature(e) {
|
|
642
|
-
return
|
|
645
|
+
return At(this.svgRendererInstance, this.strategyInstance, e, Et);
|
|
643
646
|
}
|
|
644
647
|
/**
|
|
645
648
|
* Draws a note on the staff.
|
|
@@ -663,20 +666,20 @@ class Rt {
|
|
|
663
666
|
*/
|
|
664
667
|
drawNote(e) {
|
|
665
668
|
const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayerByName("notes"), r = [];
|
|
666
|
-
for (const
|
|
667
|
-
let
|
|
669
|
+
for (const n of t) {
|
|
670
|
+
let o;
|
|
668
671
|
try {
|
|
669
|
-
|
|
672
|
+
o = this.noteRendererInstance.renderNote(n);
|
|
670
673
|
} catch (i) {
|
|
671
674
|
throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), i;
|
|
672
675
|
}
|
|
673
|
-
|
|
674
|
-
gElement:
|
|
675
|
-
note:
|
|
676
|
-
xPos: this.noteCursorX +
|
|
677
|
-
yPos:
|
|
678
|
-
accidentalXOffset:
|
|
679
|
-
}), this.noteCursorX += 28 +
|
|
676
|
+
o.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + o.accidentalOffset}, ${o.noteYPos})`), this.noteEntries.push({
|
|
677
|
+
gElement: o.noteGroup,
|
|
678
|
+
note: o.noteObj,
|
|
679
|
+
xPos: this.noteCursorX + o.accidentalOffset,
|
|
680
|
+
yPos: o.noteYPos,
|
|
681
|
+
accidentalXOffset: o.accidentalOffset
|
|
682
|
+
}), this.noteCursorX += 28 + o.accidentalOffset, r.push(o.noteGroup);
|
|
680
683
|
}
|
|
681
684
|
this.svgRendererInstance.commitElementsToDOM(r, s);
|
|
682
685
|
}
|
|
@@ -700,7 +703,7 @@ class Rt {
|
|
|
700
703
|
const t = this.svgRendererInstance.getLayerByName("notes"), s = this.noteRendererInstance.renderChord(e);
|
|
701
704
|
s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
|
|
702
705
|
gElement: s.noteGroup,
|
|
703
|
-
note:
|
|
706
|
+
note: U(e[0]),
|
|
704
707
|
xPos: this.noteCursorX + s.accidentalOffset,
|
|
705
708
|
yPos: 0,
|
|
706
709
|
accidentalXOffset: s.accidentalOffset
|
|
@@ -714,16 +717,16 @@ class Rt {
|
|
|
714
717
|
const e = this.options.width - this.noteStartX, t = this.noteEntries.length;
|
|
715
718
|
if (t <= 0 || e <= 0) return;
|
|
716
719
|
const s = Math.round(e / t);
|
|
717
|
-
this.noteEntries.map((
|
|
718
|
-
const i = (
|
|
720
|
+
this.noteEntries.map((n, o) => {
|
|
721
|
+
const i = (o + 0.5) * s, a = n.gElement.getBBox(), c = i - a.width / 2 - a.x, l = Math.round(c * 10) / 10;
|
|
719
722
|
return {
|
|
720
|
-
entry:
|
|
723
|
+
entry: n,
|
|
721
724
|
newX: l,
|
|
722
|
-
isChord:
|
|
725
|
+
isChord: n.gElement.classList.contains("chord")
|
|
723
726
|
};
|
|
724
|
-
}).forEach((
|
|
725
|
-
const { entry:
|
|
726
|
-
a ?
|
|
727
|
+
}).forEach((n) => {
|
|
728
|
+
const { entry: o, newX: i, isChord: a } = n;
|
|
729
|
+
a ? o.gElement.setAttribute("transform", `translate(${i}, 0)`) : o.gElement.setAttribute("transform", `translate(${i}, ${o.yPos})`), o.xPos = i;
|
|
727
730
|
});
|
|
728
731
|
}
|
|
729
732
|
/**
|
|
@@ -751,11 +754,11 @@ class Rt {
|
|
|
751
754
|
*/
|
|
752
755
|
changeNoteByIndex(e, t) {
|
|
753
756
|
if (t >= this.noteEntries.length) throw new Error("Note index was out of bounds.");
|
|
754
|
-
const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e),
|
|
755
|
-
r.noteGroup.setAttribute("transform", `translate(${
|
|
757
|
+
const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
|
|
758
|
+
r.noteGroup.setAttribute("transform", `translate(${o}, ${r.noteYPos})`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
|
|
756
759
|
gElement: r.noteGroup,
|
|
757
760
|
note: r.noteObj,
|
|
758
|
-
xPos:
|
|
761
|
+
xPos: o,
|
|
759
762
|
yPos: r.noteYPos,
|
|
760
763
|
accidentalXOffset: r.accidentalOffset
|
|
761
764
|
};
|
|
@@ -779,11 +782,11 @@ class Rt {
|
|
|
779
782
|
changeChordByIndex(e, t) {
|
|
780
783
|
if (t >= this.noteEntries.length) throw new Error("Chord index was out of bounds.");
|
|
781
784
|
if (e.length < 2) throw new Error("Notes provided need to be more than one to be considered a chord.");
|
|
782
|
-
const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e),
|
|
783
|
-
r.noteGroup.setAttribute("transform", `translate(${
|
|
785
|
+
const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
|
|
786
|
+
r.noteGroup.setAttribute("transform", `translate(${o}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
|
|
784
787
|
gElement: r.noteGroup,
|
|
785
|
-
note:
|
|
786
|
-
xPos:
|
|
788
|
+
note: U(e[0]),
|
|
789
|
+
xPos: o,
|
|
787
790
|
yPos: 0,
|
|
788
791
|
accidentalXOffset: r.accidentalOffset
|
|
789
792
|
};
|
|
@@ -818,7 +821,7 @@ class Rt {
|
|
|
818
821
|
this.noteEntries = [], this.svgRendererInstance.destroy();
|
|
819
822
|
}
|
|
820
823
|
}
|
|
821
|
-
const
|
|
824
|
+
const I = 30, J = 19, F = 12, St = 4, Nt = 6, tt = 1, D = 38, Lt = [
|
|
822
825
|
"TIME_4",
|
|
823
826
|
"TIME_3",
|
|
824
827
|
"NOTE_HEAD_WHOLE",
|
|
@@ -830,7 +833,7 @@ const A = 30, z = 19, O = 12, _t = 4, Tt = 6, j = 1, b = 38, mt = [
|
|
|
830
833
|
"REST_QUARTER",
|
|
831
834
|
"REST_EIGHTH"
|
|
832
835
|
];
|
|
833
|
-
class
|
|
836
|
+
class Gt {
|
|
834
837
|
rendererInstance;
|
|
835
838
|
options;
|
|
836
839
|
barSpacing;
|
|
@@ -841,7 +844,7 @@ class yt {
|
|
|
841
844
|
currentBeatCount = 0;
|
|
842
845
|
currentBeatUICount = 0;
|
|
843
846
|
currentBeatUIElement = null;
|
|
844
|
-
currentBeatUIXPos =
|
|
847
|
+
currentBeatUIXPos = D;
|
|
845
848
|
/**
|
|
846
849
|
* Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
|
|
847
850
|
*
|
|
@@ -861,13 +864,13 @@ class yt {
|
|
|
861
864
|
staffBackgroundColor: "white",
|
|
862
865
|
currentBeatUIColor: "#24ff7450",
|
|
863
866
|
...t
|
|
864
|
-
}, this.rendererInstance = new
|
|
867
|
+
}, this.rendererInstance = new w(e, {
|
|
865
868
|
width: this.options.width,
|
|
866
869
|
height: 100,
|
|
867
870
|
scale: this.options.scale,
|
|
868
871
|
staffColor: this.options.staffColor,
|
|
869
872
|
staffBackgroundColor: this.options.staffBackgroundColor,
|
|
870
|
-
useGlyphs:
|
|
873
|
+
useGlyphs: Lt
|
|
871
874
|
});
|
|
872
875
|
const s = this.rendererInstance.rootSvgElement;
|
|
873
876
|
let r = "TIME_4";
|
|
@@ -883,41 +886,41 @@ class yt {
|
|
|
883
886
|
}
|
|
884
887
|
if (this.options.barsCount < 1 || this.options.barsCount > 3) throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);
|
|
885
888
|
if (this.options.spaceAbove) {
|
|
886
|
-
const
|
|
887
|
-
this.rendererInstance.addTotalRootSvgYOffset(
|
|
889
|
+
const f = this.options.spaceAbove * 10;
|
|
890
|
+
this.rendererInstance.addTotalRootSvgYOffset(f);
|
|
888
891
|
}
|
|
889
892
|
if (this.options.spaceBelow) {
|
|
890
|
-
let
|
|
891
|
-
this.rendererInstance.addTotalRootSvgHeight(
|
|
893
|
+
let f = this.options.spaceBelow * 10;
|
|
894
|
+
this.rendererInstance.addTotalRootSvgHeight(f);
|
|
892
895
|
}
|
|
893
|
-
const
|
|
894
|
-
this.rendererInstance.addTotalRootSvgHeight(
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
const i =
|
|
898
|
-
this.rendererInstance.drawGlyph(r,
|
|
896
|
+
const n = this.rendererInstance.getLayerByName("staff");
|
|
897
|
+
this.rendererInstance.addTotalRootSvgHeight(I * 2);
|
|
898
|
+
const o = this.rendererInstance.createGroup("time-signature");
|
|
899
|
+
n.appendChild(o);
|
|
900
|
+
const i = I - J;
|
|
901
|
+
this.rendererInstance.drawGlyph(r, o), this.rendererInstance.drawGlyph("TIME_4", o, { yOffset: J }), o.setAttribute("transform", `translate(0, ${i})`);
|
|
899
902
|
let a = this.options.width - 38;
|
|
900
|
-
this.options.barsCount > 1 && (a -= (this.options.barsCount - 1) *
|
|
903
|
+
this.options.barsCount > 1 && (a -= (this.options.barsCount - 1) * F), a -= tt, this.rendererInstance.drawLine(0, I, this.options.width - tt, I, n), this.barSpacing = a / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
|
|
901
904
|
let c = this.barSpacing + 38;
|
|
902
|
-
const l =
|
|
903
|
-
for (let
|
|
904
|
-
this.rendererInstance.drawLine(c, l, c, d,
|
|
905
|
-
this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${
|
|
905
|
+
const l = I / 2, d = I + l;
|
|
906
|
+
for (let f = 0; f < this.options.barsCount - 1; f++)
|
|
907
|
+
this.rendererInstance.drawLine(c, l, c, d, n), c += this.barSpacing;
|
|
908
|
+
this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${I})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
|
|
906
909
|
}
|
|
907
910
|
createBeatUIElement() {
|
|
908
911
|
const e = this.rendererInstance.getLayerByName("ui");
|
|
909
912
|
this.currentBeatUIElement = this.rendererInstance.drawRect(
|
|
910
913
|
this.quarterNoteSpacing / 2,
|
|
911
|
-
|
|
914
|
+
I * 2,
|
|
912
915
|
e,
|
|
913
916
|
{
|
|
914
|
-
x:
|
|
917
|
+
x: D,
|
|
915
918
|
fill: this.options.currentBeatUIColor
|
|
916
919
|
}
|
|
917
920
|
);
|
|
918
921
|
}
|
|
919
922
|
handleNewBar() {
|
|
920
|
-
this.noteCursorX +=
|
|
923
|
+
this.noteCursorX += F;
|
|
921
924
|
}
|
|
922
925
|
// Translates group, returns cursor increment amount
|
|
923
926
|
translateGroupByDuration(e, t) {
|
|
@@ -976,15 +979,15 @@ class yt {
|
|
|
976
979
|
let s = e;
|
|
977
980
|
for (; s > 0; ) {
|
|
978
981
|
const r = this.rendererInstance.createGroup("rest");
|
|
979
|
-
let
|
|
980
|
-
s - p.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r),
|
|
982
|
+
let n = 0;
|
|
983
|
+
s - p.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), n = p.h) : s - p.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), n = p.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), n = p.e), s -= n, this.currentBeatCount += n, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += n * this.quarterNoteSpacing, t.push(r);
|
|
981
984
|
}
|
|
982
985
|
return t;
|
|
983
986
|
}
|
|
984
987
|
renderBeamRect(e, t, s, r) {
|
|
985
988
|
this.rendererInstance.drawRect(
|
|
986
989
|
e - t,
|
|
987
|
-
|
|
990
|
+
St,
|
|
988
991
|
s,
|
|
989
992
|
{
|
|
990
993
|
x: 10,
|
|
@@ -1013,14 +1016,14 @@ class yt {
|
|
|
1013
1016
|
*/
|
|
1014
1017
|
drawNote(e) {
|
|
1015
1018
|
const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
|
|
1016
|
-
for (const
|
|
1017
|
-
let
|
|
1019
|
+
for (const n of t) {
|
|
1020
|
+
let o = "w";
|
|
1018
1021
|
try {
|
|
1019
|
-
|
|
1022
|
+
o = b(n);
|
|
1020
1023
|
} catch (d) {
|
|
1021
1024
|
throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
|
|
1022
1025
|
}
|
|
1023
|
-
const i = p[
|
|
1026
|
+
const i = p[o];
|
|
1024
1027
|
if (this.currentBeatCount >= this.maxBeatCount)
|
|
1025
1028
|
throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
|
|
1026
1029
|
this.checkAndCreateNewBar();
|
|
@@ -1029,7 +1032,7 @@ class yt {
|
|
|
1029
1032
|
r.push(d), this.noteEntries.push(d);
|
|
1030
1033
|
});
|
|
1031
1034
|
const c = this.rendererInstance.createGroup("note"), l = this.translateGroupByDuration(i, c);
|
|
1032
|
-
this.noteCursorX += l, this.currentBeatCount += i, this.renderNote(
|
|
1035
|
+
this.noteCursorX += l, this.currentBeatCount += i, this.renderNote(o, c), r.push(c), this.noteEntries.push(c);
|
|
1033
1036
|
}
|
|
1034
1037
|
this.rendererInstance.commitElementsToDOM(r, s);
|
|
1035
1038
|
}
|
|
@@ -1053,21 +1056,21 @@ class yt {
|
|
|
1053
1056
|
*/
|
|
1054
1057
|
drawRest(e) {
|
|
1055
1058
|
const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
|
|
1056
|
-
for (const
|
|
1057
|
-
let
|
|
1059
|
+
for (const n of t) {
|
|
1060
|
+
let o = "w";
|
|
1058
1061
|
try {
|
|
1059
|
-
|
|
1062
|
+
o = b(n);
|
|
1060
1063
|
} catch (d) {
|
|
1061
1064
|
throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
|
|
1062
1065
|
}
|
|
1063
|
-
const i = this.rendererInstance.createGroup("rest"), a = p[
|
|
1066
|
+
const i = this.rendererInstance.createGroup("rest"), a = p[o], c = a * this.quarterNoteSpacing;
|
|
1064
1067
|
if (this.currentBeatCount >= this.maxBeatCount)
|
|
1065
1068
|
throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
|
|
1066
1069
|
this.checkAndCreateNewBar();
|
|
1067
1070
|
const l = this.checkAndFillBarWithRests(a);
|
|
1068
1071
|
l && l.forEach((d) => {
|
|
1069
1072
|
r.push(d), this.noteEntries.push(d);
|
|
1070
|
-
}), this.renderRest(
|
|
1073
|
+
}), this.renderRest(o, i), i.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += c, this.currentBeatCount += a, r.push(i), this.noteEntries.push(i);
|
|
1071
1074
|
}
|
|
1072
1075
|
this.rendererInstance.commitElementsToDOM(r, s);
|
|
1073
1076
|
}
|
|
@@ -1094,13 +1097,13 @@ class yt {
|
|
|
1094
1097
|
if (this.currentBeatCount >= this.maxBeatCount)
|
|
1095
1098
|
throw new Error("Max beat count reached. Can't add additional beamed note.");
|
|
1096
1099
|
let s = "s";
|
|
1097
|
-
e === "s" ? s = "s" : s =
|
|
1098
|
-
const r = this.rendererInstance.getLayerByName("notes"),
|
|
1100
|
+
e === "s" ? s = "s" : s = b(e), this.checkAndCreateNewBar();
|
|
1101
|
+
const r = this.rendererInstance.getLayerByName("notes"), n = p[s], o = n * this.quarterNoteSpacing, i = this.options.topNumber - this.currentBeatCount % this.options.topNumber, a = Math.min(t, i / n), c = this.rendererInstance.createGroup("beamed-note");
|
|
1099
1102
|
c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
|
|
1100
1103
|
let l = 0;
|
|
1101
1104
|
for (let d = 0; d < a; d++)
|
|
1102
|
-
this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l +=
|
|
1103
|
-
this.renderBeamRect(l,
|
|
1105
|
+
this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l += o, this.currentBeatCount += n;
|
|
1106
|
+
this.renderBeamRect(l, o, c), e === "s" && this.renderBeamRect(l, o, c, Nt), this.noteCursorX += l, this.noteEntries.push(c), this.rendererInstance.commitElementsToDOM(c, r);
|
|
1104
1107
|
}
|
|
1105
1108
|
/**
|
|
1106
1109
|
* Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
|
|
@@ -1111,14 +1114,14 @@ class yt {
|
|
|
1111
1114
|
this.currentBeatUIElement.setAttribute("display", "none");
|
|
1112
1115
|
return;
|
|
1113
1116
|
}
|
|
1114
|
-
this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos +=
|
|
1117
|
+
this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += F), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
|
|
1115
1118
|
}
|
|
1116
1119
|
/**
|
|
1117
1120
|
* Resets the ui showing the current beat value.
|
|
1118
1121
|
* @returns void
|
|
1119
1122
|
*/
|
|
1120
1123
|
resetCurrentBeatUI() {
|
|
1121
|
-
this.currentBeatUICount = 0, this.currentBeatUIXPos =
|
|
1124
|
+
this.currentBeatUICount = 0, this.currentBeatUIXPos = D, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
|
|
1122
1125
|
}
|
|
1123
1126
|
/**
|
|
1124
1127
|
* Clears staff of notes and resets internal positioning.
|
|
@@ -1135,7 +1138,7 @@ class yt {
|
|
|
1135
1138
|
this.noteEntries = [], this.rendererInstance.destroy();
|
|
1136
1139
|
}
|
|
1137
1140
|
}
|
|
1138
|
-
const
|
|
1141
|
+
const Rt = [
|
|
1139
1142
|
"CLEF_TREBLE",
|
|
1140
1143
|
"CLEF_BASS",
|
|
1141
1144
|
"CLEF_ALTO",
|
|
@@ -1149,8 +1152,8 @@ const Ct = [
|
|
|
1149
1152
|
"ACCIDENTAL_NATURAL",
|
|
1150
1153
|
"ACCIDENTAL_DOUBLE_SHARP",
|
|
1151
1154
|
"ACCIDENTAL_DOUBLE_FLAT"
|
|
1152
|
-
],
|
|
1153
|
-
class
|
|
1155
|
+
], y = 60, yt = y;
|
|
1156
|
+
class vt {
|
|
1154
1157
|
svgRendererInstance;
|
|
1155
1158
|
strategyInstance;
|
|
1156
1159
|
noteRendererInstance;
|
|
@@ -1177,32 +1180,32 @@ class wt {
|
|
|
1177
1180
|
staffColor: "black",
|
|
1178
1181
|
staffBackgroundColor: "transparent",
|
|
1179
1182
|
...t
|
|
1180
|
-
}, this.svgRendererInstance = new
|
|
1183
|
+
}, this.svgRendererInstance = new w(e, {
|
|
1181
1184
|
width: this.options.width,
|
|
1182
1185
|
height: 100,
|
|
1183
1186
|
scale: this.options.scale,
|
|
1184
1187
|
staffColor: this.options.staffColor,
|
|
1185
1188
|
staffBackgroundColor: this.options.staffBackgroundColor,
|
|
1186
|
-
useGlyphs:
|
|
1189
|
+
useGlyphs: Rt
|
|
1187
1190
|
});
|
|
1188
1191
|
const s = this.svgRendererInstance.rootSvgElement;
|
|
1189
1192
|
switch (this.options.staffType) {
|
|
1190
1193
|
case "grand":
|
|
1191
|
-
this.strategyInstance = new
|
|
1194
|
+
this.strategyInstance = new ot(this.svgRendererInstance, "grand");
|
|
1192
1195
|
break;
|
|
1193
1196
|
case "bass":
|
|
1194
|
-
this.strategyInstance = new
|
|
1197
|
+
this.strategyInstance = new m(this.svgRendererInstance, "bass");
|
|
1195
1198
|
break;
|
|
1196
1199
|
case "treble":
|
|
1197
|
-
this.strategyInstance = new
|
|
1200
|
+
this.strategyInstance = new m(this.svgRendererInstance, "treble");
|
|
1198
1201
|
break;
|
|
1199
1202
|
case "alto":
|
|
1200
|
-
this.strategyInstance = new
|
|
1203
|
+
this.strategyInstance = new m(this.svgRendererInstance, "alto");
|
|
1201
1204
|
break;
|
|
1202
1205
|
default:
|
|
1203
1206
|
throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
|
|
1204
1207
|
}
|
|
1205
|
-
if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new
|
|
1208
|
+
if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
|
|
1206
1209
|
const r = this.options.spaceAbove * 10;
|
|
1207
1210
|
this.svgRendererInstance.addTotalRootSvgYOffset(r);
|
|
1208
1211
|
}
|
|
@@ -1213,10 +1216,10 @@ class wt {
|
|
|
1213
1216
|
this.notesLayer = this.svgRendererInstance.getLayerByName("notes"), this.notesLayer.classList.add("vs-scrolling-notes-layer"), this.noteStartX = 38 + this.options.noteStartX, this.svgRendererInstance.getLayerByName("notes").setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
|
|
1214
1217
|
}
|
|
1215
1218
|
renderFirstNoteGroups() {
|
|
1216
|
-
const e = this.options.width - this.options.noteStartX +
|
|
1219
|
+
const e = this.options.width - this.options.noteStartX + yt;
|
|
1217
1220
|
for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
|
|
1218
|
-
this.renderNextNote(), this.noteCursorX +=
|
|
1219
|
-
this.activeEntries.length > 1 && (this.noteCursorX -=
|
|
1221
|
+
this.renderNextNote(), this.noteCursorX += y;
|
|
1222
|
+
this.activeEntries.length > 1 && (this.noteCursorX -= y);
|
|
1220
1223
|
}
|
|
1221
1224
|
renderNextNote() {
|
|
1222
1225
|
if (this.noteBuffer.length < 1) return;
|
|
@@ -1275,7 +1278,7 @@ class wt {
|
|
|
1275
1278
|
return;
|
|
1276
1279
|
}
|
|
1277
1280
|
this.activeEntries.forEach((t) => {
|
|
1278
|
-
t.xPos -=
|
|
1281
|
+
t.xPos -= y, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
|
|
1279
1282
|
});
|
|
1280
1283
|
const e = this.activeEntries[0];
|
|
1281
1284
|
e.xPos <= 0 && (this.notesLayer.removeChild(e.noteWrapper), this.activeEntries.shift()), this.renderNextNote();
|
|
@@ -1295,8 +1298,8 @@ class wt {
|
|
|
1295
1298
|
this.svgRendererInstance.destroy(), this.activeEntries = [], this.noteBuffer = [];
|
|
1296
1299
|
}
|
|
1297
1300
|
}
|
|
1298
|
-
const
|
|
1299
|
-
function
|
|
1301
|
+
const wt = /^[xX\da-zA-Z]+$/, Ot = /^[\d]+$/;
|
|
1302
|
+
function et(h, e) {
|
|
1300
1303
|
const t = [];
|
|
1301
1304
|
for (let s = 0; s < h.length; s++)
|
|
1302
1305
|
t.push({
|
|
@@ -1305,27 +1308,26 @@ function K(h, e) {
|
|
|
1305
1308
|
});
|
|
1306
1309
|
return t;
|
|
1307
1310
|
}
|
|
1308
|
-
function
|
|
1309
|
-
const t = h.filter((
|
|
1311
|
+
function st(h, e) {
|
|
1312
|
+
const t = h.filter((n) => n.toLowerCase() !== "x" && n !== "0").map((n) => parseInt(n, 36));
|
|
1310
1313
|
if (t.length === 0) return 1;
|
|
1311
1314
|
const s = Math.min(...t);
|
|
1312
1315
|
return Math.max(...t) <= e ? 1 : s;
|
|
1313
1316
|
}
|
|
1314
|
-
function
|
|
1315
|
-
if (!
|
|
1317
|
+
function H(h) {
|
|
1318
|
+
if (!wt.test(h)) throw new Error("Invalid frets string. Only 'x', 'X', and digits are allowed.");
|
|
1316
1319
|
return h.split("");
|
|
1317
1320
|
}
|
|
1318
|
-
function
|
|
1319
|
-
if (!
|
|
1321
|
+
function B(h) {
|
|
1322
|
+
if (!Ot.test(h)) throw new Error("Invalid fingers string. Only digits are allowed.");
|
|
1320
1323
|
return h.split("");
|
|
1321
1324
|
}
|
|
1322
|
-
class
|
|
1325
|
+
class Ft {
|
|
1323
1326
|
svgRendererInstance;
|
|
1324
1327
|
options;
|
|
1325
1328
|
chordEntries = [];
|
|
1326
1329
|
cursorX = 0;
|
|
1327
1330
|
cursorY = 0;
|
|
1328
|
-
// Fixed per-instance sizing, derived once from options
|
|
1329
1331
|
diagramWidth;
|
|
1330
1332
|
diagramHeight;
|
|
1331
1333
|
gridTopY;
|
|
@@ -1339,17 +1341,17 @@ class Ot {
|
|
|
1339
1341
|
*/
|
|
1340
1342
|
constructor(e, t) {
|
|
1341
1343
|
if (this.options = {
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
stringCount: st,
|
|
1345
|
-
fretCount: rt,
|
|
1344
|
+
stringCount: at,
|
|
1345
|
+
fretCount: ct,
|
|
1346
1346
|
stringLabels: [],
|
|
1347
|
+
inlineChordsAmount: 2,
|
|
1348
|
+
scale: 1,
|
|
1347
1349
|
color: "black",
|
|
1348
1350
|
backgroundColor: "transparent",
|
|
1349
1351
|
...t
|
|
1350
|
-
}, this.diagramWidth = (this.options.stringCount - 1) *
|
|
1352
|
+
}, this.diagramWidth = (this.options.stringCount - 1) * _, this.diagramHeight = this.options.fretCount * T, this.gridTopY = Z + W, this.rowHeight = this.gridTopY + this.diagramHeight + $, t?.width ? this.options.width = t.width : this.options.width = (this.diagramWidth + M) * this.options.inlineChordsAmount, this.options.stringLabels.length >= 1 && (this.rowHeight += lt + ht), this.diagramWidth > this.options.width)
|
|
1351
1353
|
throw new Error(`The configured width (${this.options.width}) is too small to fit a single ${this.options.stringCount}-string diagram (needs at least ${this.diagramWidth}). Increase 'width'.`);
|
|
1352
|
-
this.svgRendererInstance = new
|
|
1354
|
+
this.svgRendererInstance = new w(e, {
|
|
1353
1355
|
width: this.options.width,
|
|
1354
1356
|
height: 100,
|
|
1355
1357
|
scale: this.options.scale,
|
|
@@ -1360,24 +1362,38 @@ class Ot {
|
|
|
1360
1362
|
const s = this.svgRendererInstance.rootSvgElement;
|
|
1361
1363
|
this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
|
|
1362
1364
|
}
|
|
1363
|
-
|
|
1364
|
-
const
|
|
1365
|
-
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1365
|
+
getDotsToHide(e) {
|
|
1366
|
+
const t = /* @__PURE__ */ new Set();
|
|
1367
|
+
return e && e.forEach((s) => {
|
|
1368
|
+
const r = s.fromString - 1, n = s.toString - 1;
|
|
1369
|
+
for (let o = r; o <= n; o++)
|
|
1370
|
+
t.add(`${o}-${s.fret}`);
|
|
1371
|
+
}), t;
|
|
1372
|
+
}
|
|
1373
|
+
drawFretDots(e, t, s, r, n) {
|
|
1374
|
+
const o = this.gridTopY - W / 2;
|
|
1375
|
+
for (let i = 0; i < this.options.stringCount; i++) {
|
|
1376
|
+
const a = i * _, c = e[i].toLowerCase(), l = t[i];
|
|
1377
|
+
if (c === "x")
|
|
1378
|
+
this.svgRendererInstance.drawLine(a - g, o - g, a + g, o + g, n), this.svgRendererInstance.drawLine(a - g, o + g, a + g, o - g, n);
|
|
1379
|
+
else if (c === "0")
|
|
1380
|
+
this.svgRendererInstance.drawCircle(a, o, g, n, { filled: !1 });
|
|
1371
1381
|
else {
|
|
1372
|
-
const
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1375
|
-
const
|
|
1376
|
-
if (
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1382
|
+
const d = parseInt(c, 36);
|
|
1383
|
+
if (r.has(`${i}-${d}`))
|
|
1384
|
+
continue;
|
|
1385
|
+
const f = d - s + 1;
|
|
1386
|
+
if (f < 1 || f > this.options.fretCount)
|
|
1387
|
+
throw new Error(`Fret ${c} on string ${i + 1} is outside the visible range (${s}-${s + this.options.fretCount - 1}). Adjust 'startFret' or 'fretCount'.`);
|
|
1388
|
+
const C = this.gridTopY + (f - 0.5) * T;
|
|
1389
|
+
if (this.svgRendererInstance.drawCircle(a, C, u, n, {
|
|
1390
|
+
classes: "guitar-fret-dot"
|
|
1391
|
+
}), l !== "0") {
|
|
1392
|
+
const E = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
|
|
1393
|
+
this.svgRendererInstance.drawText(l, a, C + S / 3, n, {
|
|
1394
|
+
fontSize: S,
|
|
1395
|
+
fill: E,
|
|
1396
|
+
classes: "guitar-text-small"
|
|
1381
1397
|
});
|
|
1382
1398
|
}
|
|
1383
1399
|
}
|
|
@@ -1385,12 +1401,15 @@ class Ot {
|
|
|
1385
1401
|
}
|
|
1386
1402
|
drawStringLabels(e, t) {
|
|
1387
1403
|
if (!t || t.length === 0) return;
|
|
1388
|
-
const s =
|
|
1389
|
-
for (let
|
|
1390
|
-
const
|
|
1391
|
-
if (!
|
|
1392
|
-
const i =
|
|
1393
|
-
this.svgRendererInstance.
|
|
1404
|
+
const s = u, r = this.rowHeight - s - $;
|
|
1405
|
+
for (let n = 0; n < this.options.stringCount; n++) {
|
|
1406
|
+
const o = t[n];
|
|
1407
|
+
if (!o) continue;
|
|
1408
|
+
const i = n * _, a = r + s / 2;
|
|
1409
|
+
this.svgRendererInstance.drawText(o, i, a, e, {
|
|
1410
|
+
fontSize: S,
|
|
1411
|
+
classes: "guitar-text-small"
|
|
1412
|
+
});
|
|
1394
1413
|
}
|
|
1395
1414
|
}
|
|
1396
1415
|
// Passed in 'from' and 'to' index values are zero-based
|
|
@@ -1400,61 +1419,66 @@ class Ot {
|
|
|
1400
1419
|
throw new Error(`Barre fret error: Invalid string range ${t.fromIndex + 1}:${t.toIndex + 1}.`);
|
|
1401
1420
|
if (s < t.startingFret || s > t.startingFret + (this.options.fretCount - 1))
|
|
1402
1421
|
throw new Error(`Barre fret error: ${t.fret} is outside the visible range.`);
|
|
1403
|
-
const r = s - t.startingFret,
|
|
1422
|
+
const r = s - t.startingFret, n = t.fromIndex * _, o = t.toIndex * _, i = u * 2, a = o - n + i, c = this.gridTopY + u / 2 + T * r, l = this.gridTopY + T * r + u * 2;
|
|
1404
1423
|
if (this.svgRendererInstance.drawRect(a, i, e, {
|
|
1405
|
-
x:
|
|
1424
|
+
x: n - u,
|
|
1406
1425
|
y: c,
|
|
1407
|
-
rx:
|
|
1426
|
+
rx: u,
|
|
1427
|
+
classes: "guitar-barre"
|
|
1408
1428
|
}), t.finger) {
|
|
1409
|
-
const
|
|
1410
|
-
this.svgRendererInstance.drawText(t.finger.toString(), (
|
|
1411
|
-
fontSize:
|
|
1412
|
-
fill:
|
|
1429
|
+
const d = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
|
|
1430
|
+
this.svgRendererInstance.drawText(t.finger.toString(), (n + o) / 2, l, e, {
|
|
1431
|
+
fontSize: S,
|
|
1432
|
+
fill: d,
|
|
1433
|
+
classes: "guitar-text-small"
|
|
1413
1434
|
});
|
|
1414
1435
|
}
|
|
1415
1436
|
}
|
|
1416
1437
|
// Builds a single chord diagram's group element: grid, nut/fret-position label, and per-string markers.
|
|
1417
1438
|
renderChordDiagram(e, t, s) {
|
|
1418
|
-
const r = this.svgRendererInstance.createGroup("chord"),
|
|
1419
|
-
s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2,
|
|
1420
|
-
fontSize:
|
|
1421
|
-
fontWeight: "bold"
|
|
1439
|
+
const r = this.svgRendererInstance.createGroup("chord"), n = s?.startFret ?? 1;
|
|
1440
|
+
s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2, Z - 5, r, {
|
|
1441
|
+
fontSize: rt,
|
|
1442
|
+
fontWeight: "bold",
|
|
1443
|
+
classes: "guitar-text-base"
|
|
1422
1444
|
});
|
|
1423
|
-
for (let
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1426
|
-
x: -
|
|
1427
|
-
y:
|
|
1428
|
-
}) : this.svgRendererInstance.drawLine(0,
|
|
1445
|
+
for (let i = 0; i <= this.options.fretCount; i++) {
|
|
1446
|
+
const a = this.gridTopY + i * T;
|
|
1447
|
+
i === 0 && n === 1 ? this.svgRendererInstance.drawRect(this.diagramWidth + k * 2, P, r, {
|
|
1448
|
+
x: -k,
|
|
1449
|
+
y: a - P / 2
|
|
1450
|
+
}) : this.svgRendererInstance.drawLine(0, a, this.diagramWidth, a, r);
|
|
1429
1451
|
}
|
|
1430
|
-
|
|
1452
|
+
n > 1 && this.svgRendererInstance.drawText(`${n}fr`, this.diagramWidth + u + ut, this.gridTopY + T / 2 + 4, r, {
|
|
1431
1453
|
anchor: "start",
|
|
1432
|
-
fontSize:
|
|
1433
|
-
fontWeight: "bold"
|
|
1454
|
+
fontSize: S,
|
|
1455
|
+
fontWeight: "bold",
|
|
1456
|
+
classes: "guitar-text-small"
|
|
1434
1457
|
});
|
|
1435
|
-
for (let
|
|
1436
|
-
const
|
|
1437
|
-
this.svgRendererInstance.drawLine(
|
|
1458
|
+
for (let i = 0; i < this.options.stringCount; i++) {
|
|
1459
|
+
const a = i * _;
|
|
1460
|
+
this.svgRendererInstance.drawLine(a, this.gridTopY, a, this.gridTopY + this.diagramHeight, r);
|
|
1438
1461
|
}
|
|
1439
|
-
|
|
1462
|
+
const o = this.getDotsToHide(s?.barres);
|
|
1463
|
+
return this.drawFretDots(e, t, n, o, r), this.options.stringLabels.length >= 1 && this.drawStringLabels(r, this.options.stringLabels), s?.barres?.forEach((i) => {
|
|
1440
1464
|
this.drawBarre(r, {
|
|
1441
|
-
fromIndex:
|
|
1442
|
-
toIndex:
|
|
1443
|
-
fret:
|
|
1444
|
-
finger:
|
|
1445
|
-
startingFret:
|
|
1465
|
+
fromIndex: i.fromString - 1,
|
|
1466
|
+
toIndex: i.toString - 1,
|
|
1467
|
+
fret: i.fret,
|
|
1468
|
+
finger: i.finger,
|
|
1469
|
+
startingFret: n
|
|
1446
1470
|
});
|
|
1447
1471
|
}), r;
|
|
1448
1472
|
}
|
|
1449
1473
|
// Repositions every existing chord diagram from scratch, in order, wrapping rows as needed.
|
|
1450
1474
|
// Called after any add/remove/change so the layout never has to track incremental deltas.
|
|
1451
1475
|
relayoutChords() {
|
|
1452
|
-
if (this.cursorX =
|
|
1476
|
+
if (this.cursorX = u, this.cursorY = ft, this.chordEntries.length === 1) {
|
|
1453
1477
|
const t = this.chordEntries[0];
|
|
1454
1478
|
this.cursorX = this.options.width / 2 - this.diagramWidth / 2, t.xPos = this.cursorX, t.yPos = this.cursorY, t.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`);
|
|
1455
1479
|
} else
|
|
1456
1480
|
this.chordEntries.forEach((t, s) => {
|
|
1457
|
-
s > 0 && this.cursorX + this.diagramWidth > this.options.width && (this.cursorX =
|
|
1481
|
+
s > 0 && this.cursorX + this.diagramWidth > this.options.width && (this.cursorX = u, this.cursorY += this.rowHeight + dt), t.xPos = this.cursorX, t.yPos = this.cursorY, t.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`), this.cursorX += this.diagramWidth + M;
|
|
1458
1482
|
});
|
|
1459
1483
|
const e = this.cursorY + this.rowHeight;
|
|
1460
1484
|
this.svgRendererInstance.setTotalRootSvgHeight(e), this.svgRendererInstance.applySizingToRootSvg();
|
|
@@ -1483,13 +1507,13 @@ class Ot {
|
|
|
1483
1507
|
* guitarChord.addChord("x32010", "032010", { label: "C" });
|
|
1484
1508
|
*/
|
|
1485
1509
|
addChord(e, t, s) {
|
|
1486
|
-
const r =
|
|
1510
|
+
const r = H(e), n = B(t);
|
|
1487
1511
|
if (r.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
|
|
1488
|
-
if (
|
|
1489
|
-
const
|
|
1512
|
+
if (n.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
|
|
1513
|
+
const o = s?.startFret ?? st(r, this.options.fretCount), i = s?.label, a = s?.barres, c = { startFret: o, label: i, barres: a }, l = this.renderChordDiagram(r, n, c), d = this.svgRendererInstance.getLayerByName("notes");
|
|
1490
1514
|
return this.svgRendererInstance.commitElementsToDOM(l, d), this.chordEntries.push({
|
|
1491
1515
|
gElement: l,
|
|
1492
|
-
strings:
|
|
1516
|
+
strings: et(r, n),
|
|
1493
1517
|
...c,
|
|
1494
1518
|
xPos: 0,
|
|
1495
1519
|
yPos: 0
|
|
@@ -1521,13 +1545,13 @@ class Ot {
|
|
|
1521
1545
|
*/
|
|
1522
1546
|
modifyChordByIndex(e, t, s, r) {
|
|
1523
1547
|
if (s >= this.chordEntries.length || s < 0) throw new Error("Chord index was out of bounds.");
|
|
1524
|
-
const
|
|
1525
|
-
if (
|
|
1526
|
-
if (
|
|
1527
|
-
const i = this.chordEntries[s], a = r && "label" in r ? r.label === "" ? void 0 : r.label : i.label, c = r?.startFret ??
|
|
1548
|
+
const n = H(e), o = B(t);
|
|
1549
|
+
if (n.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
|
|
1550
|
+
if (o.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
|
|
1551
|
+
const i = this.chordEntries[s], a = r && "label" in r ? r.label === "" ? void 0 : r.label : i.label, c = r?.startFret ?? st(n, this.options.fretCount), l = { ...r, label: a, startFret: c }, d = this.renderChordDiagram(n, o, l);
|
|
1528
1552
|
this.svgRendererInstance.getLayerByName("notes").replaceChild(d, i.gElement), this.chordEntries[s] = {
|
|
1529
1553
|
gElement: d,
|
|
1530
|
-
strings:
|
|
1554
|
+
strings: et(n, o),
|
|
1531
1555
|
...l,
|
|
1532
1556
|
xPos: i.xPos,
|
|
1533
1557
|
yPos: i.yPos
|
|
@@ -1556,24 +1580,27 @@ class Ot {
|
|
|
1556
1580
|
* @returns GuitarBarreDef[]
|
|
1557
1581
|
*/
|
|
1558
1582
|
determineBarreOptions(e, t, s) {
|
|
1559
|
-
const r =
|
|
1583
|
+
const r = H(e), n = B(t), o = [];
|
|
1560
1584
|
return s.forEach((i) => {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
if (
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
}
|
|
1585
|
+
if (i === 0) return;
|
|
1586
|
+
const a = [], c = {};
|
|
1587
|
+
for (let E = 0; E < r.length; E++) {
|
|
1588
|
+
if (r[E].toLowerCase() === "x") continue;
|
|
1589
|
+
const L = parseInt(r[E], 36), O = Number(n[E]);
|
|
1590
|
+
L === i && (c[O] ? c[O] += 1 : c[O] = 1, a.push(E + 1));
|
|
1568
1591
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1592
|
+
a.sort();
|
|
1593
|
+
let l = 0, d = 0;
|
|
1594
|
+
for (const [E, L] of Object.entries(c))
|
|
1595
|
+
L > d && (d = L, l = Number(E));
|
|
1596
|
+
const f = a[0], C = a.at(-1);
|
|
1597
|
+
a.length > 1 && C && o.push({
|
|
1598
|
+
fret: i,
|
|
1599
|
+
fromString: f,
|
|
1600
|
+
toString: C,
|
|
1601
|
+
finger: l
|
|
1602
|
+
});
|
|
1603
|
+
}), o;
|
|
1577
1604
|
}
|
|
1578
1605
|
/**
|
|
1579
1606
|
* Removes the root svg element and cleans up arrays.
|
|
@@ -1584,8 +1611,8 @@ class Ot {
|
|
|
1584
1611
|
}
|
|
1585
1612
|
}
|
|
1586
1613
|
export {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1614
|
+
Ft as GuitarChord,
|
|
1615
|
+
bt as MusicStaff,
|
|
1616
|
+
Gt as RhythmStaff,
|
|
1617
|
+
vt as ScrollingStaff
|
|
1591
1618
|
};
|