125 lines
3.2 KiB
TypeScript
125 lines
3.2 KiB
TypeScript
import { tag, px } from "./svg";
|
|
import {
|
|
KeyboardKey,
|
|
KeySymbol,
|
|
Layout,
|
|
LayoutColorscheme,
|
|
SpecialSymbols,
|
|
VisualKey,
|
|
} from "./types";
|
|
|
|
function textContents(input: KeySymbol): string {
|
|
if (input === SpecialSymbols.TL || input === SpecialSymbols.TR) return "■";
|
|
|
|
return input;
|
|
}
|
|
|
|
function renderKey(
|
|
visual: VisualKey,
|
|
key: KeyboardKey,
|
|
colorscheme: LayoutColorscheme,
|
|
keySize: number,
|
|
) {
|
|
const centerX = visual.position[0] + visual.size[0] / 2;
|
|
const centerY = visual.position[1] + visual.size[1] / 2;
|
|
const textAttribs = {
|
|
"text-anchor": "middle",
|
|
"dominant-baseline": "middle",
|
|
"font-family": "Helvetica",
|
|
};
|
|
|
|
const textColor = (input: KeySymbol, _default: string): string => {
|
|
if (input === SpecialSymbols.TL) return colorscheme.tlLayerColor;
|
|
if (input === SpecialSymbols.TR) return colorscheme.trLayerColor;
|
|
return _default;
|
|
};
|
|
|
|
return tag(
|
|
"g",
|
|
{
|
|
transform:
|
|
visual.angle && visual.angle !== 0
|
|
? `rotate(${visual.angle}, ${centerX}, ${centerY})`
|
|
: undefined,
|
|
},
|
|
[
|
|
tag("rect", {
|
|
width: px(visual.size[0]),
|
|
height: px(visual.size[1]),
|
|
x: visual.position[0],
|
|
y: visual.position[1],
|
|
fill: colorscheme.keyFill,
|
|
stroke: colorscheme.keyStroke,
|
|
"stroke-width": px(2),
|
|
}),
|
|
tag(
|
|
"text",
|
|
{
|
|
x: centerX,
|
|
y: centerY,
|
|
textLength: px(keySize / 2),
|
|
fill: textColor(key.main, colorscheme.mainLayerColor),
|
|
...textAttribs,
|
|
},
|
|
textContents(key.main),
|
|
),
|
|
tag(
|
|
"text",
|
|
{
|
|
x: visual.position[0] + visual.size[0] / 6,
|
|
y: visual.position[1] + visual.size[1] / 6,
|
|
fill: textColor(key.tlLayer, colorscheme.tlLayerColor),
|
|
"font-size": "66%",
|
|
...textAttribs,
|
|
},
|
|
textContents(key.tlLayer),
|
|
),
|
|
tag(
|
|
"text",
|
|
{
|
|
x: visual.position[0] + (9 * visual.size[0]) / 10,
|
|
y: visual.position[1] + visual.size[1] / 6,
|
|
fill: textColor(key.trLayer, colorscheme.trLayerColor),
|
|
"font-size": "66%",
|
|
...textAttribs,
|
|
"text-anchor": "end",
|
|
},
|
|
textContents(key.trLayer),
|
|
),
|
|
tag(
|
|
"text",
|
|
{
|
|
x: visual.position[0] + visual.size[0] / 10,
|
|
y: visual.position[1] + (5 * visual.size[1]) / 6,
|
|
fill: textColor(key.blLayer, colorscheme.blLayerColor),
|
|
"font-size": "66%",
|
|
...textAttribs,
|
|
"text-anchor": "start",
|
|
},
|
|
textContents(key.blLayer),
|
|
),
|
|
].join("\n"),
|
|
);
|
|
}
|
|
|
|
export function renderLayout(layout: Layout) {
|
|
return tag(
|
|
"svg",
|
|
{
|
|
viewBox: [
|
|
-layout.imagePadding,
|
|
-layout.imagePadding,
|
|
2 * layout.imagePadding + layout.size[0],
|
|
2 * layout.imagePadding + layout.size[1],
|
|
].join(" "),
|
|
xmlns: "http://www.w3.org/2000/svg",
|
|
"xmlns:xlink": "http://www.w3.org/1999/xlink",
|
|
},
|
|
layout.visual
|
|
.map((key, index) =>
|
|
renderKey(key, layout.keys[index], layout.colorscheme, layout.keySize),
|
|
)
|
|
.join("\n"),
|
|
);
|
|
}
|