I want to draw ties between two notes like in this image using html css javascript svg etc.
I found a way to draw a half moon shape like this, but I can't control the width of this.
span.tie {
user-select: none;
font-family: Bravura;
--line-width: 0.03em;
position: absolute;
font-size: 1em;
line-height: 4em;
width: 1em;
height: 1em;
border-radius: 50%;
box-shadow: -0.02em 0.02em black;
transform: translate(1em, 1em) rotate(135deg);
}
<span class="tie"></span>
Because It's not exactly a half moon, it's more shallow in height more like a bezier curve.
So I used svg to manage creating this shape:
function tie(pitch: Pitch, octave: Octave, x1: number, x2: number) {
let make_mask_id = 'mask_' + [pitch, octave, x1, x2].join('_')
let y1 = pitch_y(pitch, octave)
let w = (x2 - x1) *0.4,
hw = w/ 2
let scale_y = w > 3 ? 14/w * 0.2 : 1
return h('svg.tie', {
style: {
transform: `translate(calc(${2+0.05 +x1*0.25 - w*0.16}em), calc(${y1-w*0.12-(scale_y*3-2)*0.15}
em)) scaleY(${scale_y})`
},
attrs: { width: `${w}em`, height: `${w}em`, viewBox: '0 0 100 100' }
}, [
h('defs', [
h('mask', { attrs: {
id: make_mask_id
}}, [h('circle', {
attrs: { cx: `${50}`, cy: `${50}`, r: `${200}`, fill: 'white' }
}),/*
h('rect', {
attrs: { x: 0, y: 0, width: `${hw}em`, height: `${hw}em`, fill: 'black' }
}),
*/
h('circle', {
attrs: { cx: `50`, cy: `${66-0.1*Math.sqrt(2*w)}`, r: `${60+0.4*Math.sqrt(10*w)}`, fill: 'bla
ck' }
}),
h('circle', {
attrs: { cx: `10`, cy: `50`, r: `40`, fill: 'black' }
}),
h('circle', {
attrs: { cx: `90`, cy: `50`, r: `40`, fill: 'black' }
}),
])
]), h('circle', {
attrs: { cx: `50`, cy: `50`, r: `50`, fill: 'black', mask:`url(#${make_mask_id})` }
})
] )
}
It looks like this:
<svg class="tie" width="1em" height="1em" viewBox="0 0 100 100" style="transform: translate(calc(1.9em), calc(0.48em));"><defs><mask id="m1"><circle cx="50" cy="50" r="200" fill="white"></circle><circle cx="50" cy="64" r="61" fill="black"></circle><circle cx="10" cy="50" r="40" fill="black"></circle><circle cx="90" cy="50" r="40" fill="black"></circle></mask></defs><circle cx="50" cy="50" r="50" fill="black" mask="url(#m1)"></circle></svg>
<svg class="tie" width="7em" height="7em" viewBox="0 0 100 100" style="transform: translate(calc(1em), calc(1em));"><defs><mask id="m1"><circle cx="50" cy="50" r="200" fill="white"></circle><circle cx="50" cy="52" r="67" fill="black"></circle><circle cx="10" cy="50" r="40" fill="black"></circle><circle cx="90" cy="50" r="40" fill="black"></circle></mask></defs><circle cx="50" cy="50" r="50" fill="black" mask="url(#m1)"></circle></svg>
Only problem is I can't control the thickness of this line. As the width gets bigger thickness gets too thick.
Please someone modify this solution to factor in line thickness for bigger widths.
I noticed I was using the same id, in the previous version, so I made sure each element gets a unique mask id, so that helped with the tweaking. I was wondering why my changes on the mask doesn't reflect on the render.