Cistercian Numerals (semi-golfed)
N = -1
S = 30
H = 90
h = 45
d = document
b = d.body
m = _ => d.createElement(_)
a = _ => b.appendChild(_)
with(a(
Object.assign(
m`canvas`,
{ width: 80, height: 120 }
)
).getContext`2d`
) {
a(m`br`)
L = (a, b, C, d) => {
moveTo(a, b)
lineTo(C, d)
}
M = _ => L(0, 0, 0, H)
O = _ => L(0, 0, S, 0)
W = _ => L(0, S, S, S)
T = _ => L(0, 0, S, S)
F = _ => L(0, S, S, 0)
X = _ => L(S, 0, S, S)
D = [
_ => {},
O, W, T, F,
[O,F],
X,
[O,X],
[W,X],
[O,W,X]
]
n = s => {
[...s].reverse().map((l, i) => {
save()
translate(S+9, h+9)
scale(N**i, N**~~(i/2))
translate(0, -h)
M() ;[D[l]].flat().map(x => x && x())
restore()
})
}
a(m`input`).oninput = e => {
clearRect(0, 0, 80, 120)
beginPath()
n(~~e.target.value+'')
stroke()
}
}
Type any number from 0-9999 into the input field and see the corresponding Cistercian Numeral. This snippet is partially golfed, I left the canvas commands intact to make things a bit easier to understand.
Simpler SVG Version
This one hardcodes all numbers 0-9 as paths, unlike the canvas version which only defines 1,2,3,4 and 6 as paths and then combines them to create 5,7,8 and 9.
h='innerHTML'
C='children'
document.body[h]=`
<svg id=G width=99 viewBox="0 0 80 120"
style="stroke:black;fill:none;overflow:visible">
<g transform="translate(30,2)">
<path d="M0 0L 30 0"/>
<path d="M0 30L 30 30"/>
<path d="M0 0L 30 30"/>
<path d="M0 30L30 0"/>
<path d="M0 30L30 0 0 0"/>
<path d="M30 0L30 30"/>
<path d="M30 30L30 0 0 0"/>
<path d="M0 30L30 30 30 0"/>
<path d="M0 30L30 30 30 0 0 0"/>
</g>
<g transform=translate(30,2)scale(-1,1)></g>
<g transform=translate(30,92)scale(1,-1)></g>
<g transform=translate(30,92)scale(-1,-1)></g>
<path id=m d="M 30 2 L 30 92"/>
</svg>
<style>path:not(#m){opacity:0}</style><br>
<input id=I>`
c=G[C]
p=c[0][h]
n = s =>
[...s].reverse().map((l, i) =>
l-1>-1 && (c[i][C][l-1].style.opacity=1))
I.oninput = e => {
for(i=0;i<4;i++)c[i][h]=p
n(~~e.target.value+'')
}