// 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}`); } }