The 'translate' gives the beam it's own 0,0 within the measure,
so that the transforms are centered on the upper-left hand corner of the beam;
not of the measure. The 'skewY' is the angle in degrees the beam will be;
default is clockwise, a hyphen(minus) '-' is counter clockwise.
The 'scale' is the length it will be. The number 100 is probably the most
convenient number for a default value: if the length it needs to reach is
257px, then you scale(2.57,1); or 89px: scale(.89,1).
On a standard stem* (up), the beam is placed
+14x,-85y of the note coordinates. The code for the image at right is:
* The library contains notes with long and short stems.
To calculate the angle [skewY()] of a beam, divide the interval of the notes
by the distance between them: 12 ÷ 114 = .105, which is the tangent
of the angle. With a scientific calculator, invert the tan to degrees: 6.01°.
Notice that the scale 'y' has increased also. A very small amount for this angle,
but important to know why.
As the angle increases the beam becomes narrower. The beam on the left has
no 'y' scaling. The beam on the right has been compensated. To calculate
the proportion of scale for 'y':
15 ÷ cos(angle°) ÷ 15, or:
15 ÷ [cos(6.01°)=15.08] ÷ 15 = 1.01; for the upper example, and
15 ÷ [cos(35.75°)=18.48] ÷ 15 = 1.23; for this example.
Most of the time a skewY() and a scale(,) are all you need for beams
(8th, 16th, 32nd). The exceptions are a dotted eighth note followed by a
sixteenth note, or a double dotted eighth note followed by a thirty second, etc.,
and the reverse of these; but only for notes with stem down.
This is because beams with partial beams need to be flipped. There is no flip()
transform in SVG, but there is transform="matrix(1,0,0,1,0,0)".
It would be more comfortable to take the blue pill, but the red pill will
show you how far down the rabbit hole goes.
A matrix can execute all of the transforms together:
scale, translate, skewX, skewY, rotate
or whichever ones you need.
transform="matrix(1,0,0,1,0,0)" : this changes nothing
(-1,0,0,1,0,0) : this flips x
(1,0,0,-1,0,0) : this flips y
: this scales x and y [use whatever numbers you need]
(1,0,0,1,24,6) : this translates
: this skews x [the number needs to be the tangent of the angle you want]
: this skews y [using a 1 or -1 will give a 45° angle]
: this rotates clockwise; move the minus to the first sin for counter clockwise
Notice that with matrix you use tangent rather than angle for skews.
In addition, you must multiply the tangent of skewY by the scale of 'x' to get
the correct angle. I have yet to learn how to use 'rotate' in combination with
the other properties, but you can still use rotate() and matrix().
Always rotate first!
Also, you must add 15px,y to the position of a
flipped beam (the width of a beam).
Unlike beams, slurs are rotated for angle. As with beams, the default
slur/tie is 100px long, and horizontal. It's x,y 0,0 is the left point.
The instructions for flipping a beam are the same for slur/tie's.
Placement of slurs/ties is partly a matter of taste. I've seen some sheet music
where they touch the notes, and I don't like the look of that. At right is
x+24px, y-18px, and a scale of x1.14; 12px before the next notes center
(150-24-12=114). This works well for note to note, stem up, but different
arrangements need different placement.