142 lines
5.0 KiB
JavaScript
142 lines
5.0 KiB
JavaScript
// Symbole fuer die Tasten, gezeichnet in Einheitskoordinaten [-1, 1] um (cx, cy) mit Radius r.
|
|
|
|
function heartPoints() {
|
|
const points = [];
|
|
for (let i = 0; i < 72; i += 1) {
|
|
const t = (i / 72) * Math.PI * 2;
|
|
points.push([
|
|
(16 * Math.sin(t) ** 3) / 17,
|
|
-(13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t)) / 17,
|
|
]);
|
|
}
|
|
return points;
|
|
}
|
|
const HEART = heartPoints();
|
|
|
|
export const GLYPHS = [
|
|
'play', 'pause', 'next', 'previous', 'rewind', 'forward', 'volup', 'voldown', 'vol', 'mute',
|
|
'note', 'heart', 'heartfill', 'shuffle', 'repeat', 'repeatone', 'playlist', 'tabs', 'window',
|
|
];
|
|
|
|
/**
|
|
* @param {import('./raster.mjs').Canvas} canvas
|
|
* @param {string} name - Eintrag aus GLYPHS
|
|
* @param {number} cx
|
|
* @param {number} cy
|
|
* @param {number} r - halbe Symbolgroesse in Pixeln
|
|
* @param {string} color - Symbolfarbe
|
|
* @param {string} background - Farbe hinter dem Symbol (fuer "ausgeschnittene" Formen)
|
|
*/
|
|
export function drawGlyph(canvas, name, cx, cy, r, color, background) {
|
|
const p = (x, y) => [cx + x * r, cy + y * r];
|
|
const poly = (points) => canvas.polygon(points.map(([x, y]) => p(x, y)), color);
|
|
const stroke = (x1, y1, x2, y2, w = 0.2) => {
|
|
const [ax, ay] = p(x1, y1);
|
|
const [bx, by] = p(x2, y2);
|
|
canvas.line(ax, ay, bx, by, w * r, color);
|
|
};
|
|
const path = (points, w = 0.2) => points.slice(1).forEach((pt, i) => stroke(...points[i], ...pt, w));
|
|
const speaker = (dx = 0) => poly([[-0.9 + dx, -0.3], [-0.5 + dx, -0.3], [-0.1 + dx, -0.7],
|
|
[-0.1 + dx, 0.7], [-0.5 + dx, 0.3], [-0.9 + dx, 0.3]]);
|
|
const arc = (dx, outer, inner) => {
|
|
const [ax, ay] = p(dx, 0);
|
|
canvas.ring(ax, ay, outer * r, inner * r, color, Math.PI * 2 - 0.75, Math.PI * 2);
|
|
canvas.ring(ax, ay, outer * r, inner * r, color, 0, 0.75);
|
|
};
|
|
const heart = (scale, fill) => canvas.polygon(
|
|
HEART.map(([x, y]) => [cx + x * r * scale, cy + (y * scale + 0.05) * r]), fill);
|
|
|
|
switch (name) {
|
|
case 'play':
|
|
poly([[-0.7, -0.85], [0.75, 0], [-0.7, 0.85]]);
|
|
break;
|
|
case 'pause':
|
|
poly([[-0.65, -0.8], [-0.2, -0.8], [-0.2, 0.8], [-0.65, 0.8]]);
|
|
poly([[0.2, -0.8], [0.65, -0.8], [0.65, 0.8], [0.2, 0.8]]);
|
|
break;
|
|
case 'next':
|
|
poly([[-0.8, -0.75], [0.4, 0], [-0.8, 0.75]]);
|
|
poly([[0.55, -0.75], [0.85, -0.75], [0.85, 0.75], [0.55, 0.75]]);
|
|
break;
|
|
case 'previous':
|
|
poly([[0.8, -0.75], [-0.4, 0], [0.8, 0.75]]);
|
|
poly([[-0.55, -0.75], [-0.85, -0.75], [-0.85, 0.75], [-0.55, 0.75]]);
|
|
break;
|
|
case 'rewind':
|
|
poly([[0.05, -0.65], [-0.55, 0], [0.05, 0.65]]);
|
|
poly([[0.85, -0.65], [0.25, 0], [0.85, 0.65]]);
|
|
break;
|
|
case 'forward':
|
|
poly([[-0.05, -0.65], [0.55, 0], [-0.05, 0.65]]);
|
|
poly([[-0.85, -0.65], [-0.25, 0], [-0.85, 0.65]]);
|
|
break;
|
|
case 'volup':
|
|
speaker(-0.1);
|
|
stroke(0.3, 0, 0.9, 0);
|
|
stroke(0.6, -0.3, 0.6, 0.3);
|
|
break;
|
|
case 'voldown':
|
|
speaker(-0.1);
|
|
stroke(0.3, 0, 0.9, 0);
|
|
break;
|
|
case 'vol':
|
|
speaker(-0.2);
|
|
arc(-0.3, 0.75, 0.55);
|
|
arc(-0.3, 1.1, 0.9);
|
|
break;
|
|
case 'mute':
|
|
speaker(-0.1);
|
|
stroke(0.3, -0.35, 0.9, 0.35);
|
|
stroke(0.3, 0.35, 0.9, -0.35);
|
|
break;
|
|
case 'note': {
|
|
const [nx, ny] = p(-0.35, 0.5);
|
|
canvas.circle(nx, ny, 0.38 * r, color);
|
|
stroke(0.0, 0.45, 0.0, -0.85, 0.2);
|
|
stroke(0.0, -0.85, 0.7, -0.5, 0.2);
|
|
break;
|
|
}
|
|
case 'heart':
|
|
heart(1, color);
|
|
heart(0.62, background);
|
|
break;
|
|
case 'heartfill':
|
|
heart(1, color);
|
|
break;
|
|
case 'shuffle':
|
|
path([[-0.9, 0.5], [-0.3, 0.5], [0.3, -0.5], [0.55, -0.5]], 0.18);
|
|
path([[-0.9, -0.5], [-0.3, -0.5], [0.3, 0.5], [0.55, 0.5]], 0.18);
|
|
poly([[0.5, -0.85], [0.95, -0.5], [0.5, -0.15]]);
|
|
poly([[0.5, 0.15], [0.95, 0.5], [0.5, 0.85]]);
|
|
break;
|
|
case 'repeat':
|
|
case 'repeatone':
|
|
path([[-0.8, 0.15], [-0.8, -0.4], [0.3, -0.4]], 0.18);
|
|
poly([[0.3, -0.8], [0.9, -0.4], [0.3, 0]]);
|
|
path([[0.8, -0.15], [0.8, 0.4], [-0.3, 0.4]], 0.18);
|
|
poly([[-0.3, 0.8], [-0.9, 0.4], [-0.3, 0]]);
|
|
if (name === 'repeatone') {
|
|
stroke(0.0, -0.18, 0.0, 0.2, 0.14);
|
|
stroke(-0.13, -0.1, 0.0, -0.18, 0.14);
|
|
}
|
|
break;
|
|
case 'playlist':
|
|
stroke(-0.85, -0.55, 0.15, -0.55, 0.18);
|
|
stroke(-0.85, -0.05, 0.15, -0.05, 0.18);
|
|
stroke(-0.85, 0.45, -0.25, 0.45, 0.18);
|
|
poly([[0.3, 0.05], [0.95, 0.45], [0.3, 0.85]]);
|
|
break;
|
|
case 'tabs':
|
|
canvas.roundRect(...p(-0.85, -0.7), 1.1 * r, 0.9 * r, 0.12 * r, color);
|
|
canvas.roundRect(...p(-0.75, -0.6), 0.9 * r, 0.7 * r, 0.06 * r, background);
|
|
canvas.roundRect(...p(-0.25, -0.15), 1.1 * r, 0.9 * r, 0.12 * r, color);
|
|
break;
|
|
case 'window':
|
|
canvas.roundRect(...p(-0.9, -0.7), 1.8 * r, 1.4 * r, 0.14 * r, color);
|
|
canvas.roundRect(...p(-0.75, -0.25), 1.5 * r, 0.85 * r, 0.05 * r, background);
|
|
break;
|
|
default:
|
|
throw new Error(`Unbekanntes Symbol: ${name}`);
|
|
}
|
|
}
|