-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
147 lines (124 loc) · 6.63 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
window.addEventListener('load', () => {
function element(tag, attributes) {
const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (const attribute in attributes) {
element.setAttribute(attribute, attributes[attribute]);
}
return element;
}
function rect(attributes) {
return element('rect', attributes);
}
function ellipse(attributes) {
return element('ellipse', attributes);
}
const fill = { fill: 'none' };
const stroke = { stroke: '#333', };
const strokeWidth = { 'stroke-width': '.25mm' };
const fillAndStroke = { ...fill, ...stroke, ...strokeWidth };
const roundBorder = { rx: '1mm', ...fillAndStroke };
function button(x, y) {
return [
rect({ x: `${x}mm`, y: `${y}mm`, width: '1.5cm', height: '1.5cm', ...roundBorder }),
ellipse({ cx: `${x + 7.5}mm`, cy: `${y + 7.5}mm`, rx: '5mm', ry: '5mm', stroke: '#aaa', ...fill, ...strokeWidth }),
];
}
function encoder(number) {
// TODO: Make round and rotated
const slit = rect({ x: `${128 + number * 31.05 + 15.7 - 3.5}mm`, y: `${4 + 15.7 - 1}mm`, width: '7mm', height: '2mm', ...roundBorder });
let angle = Math.random() * 360;
let speed = (Math.random() - .5) * 2;
window.setInterval(() => {
angle += speed;
slit.style = `transform-box: fill-box; transform-origin: center; transform: rotate(${angle}deg);`
});
// https://www.schemecolor.com/rainbow-pastels-color-scheme.php
const color = ['#C7CEEA', '#B5EAD7', 'white', '#FFB7B2'][number];
return [
rect({ x: `${128 + number * 31.05}mm`, y: '4mm', width: '3.05cm', height: '3.05cm', ...roundBorder }),
ellipse({ cx: `${128 + number * 31.05 + 15.7}mm`, cy: '19.7mm', rx: '9mm', ry: '9mm', stroke: '#aaa', ...fill, ...strokeWidth }),
ellipse({ cx: `${128 + number * 31.05 + 15.7}mm`, cy: '19.7mm', rx: '5mm', ry: '5mm', stroke: '#aaa', fill: color, ...strokeWidth }),
slit,
];
}
const svg = element('svg', { width: '28.45cm', height: '10.15cm' });
document.body.append(svg);
svg.append(rect({ x: '.1mm', y: '.1mm', width: '28.25cm', height: '9.95cm', rx: '4mm', fill: '#eee', stroke: '#222', 'stroke-width': '.1mm' }));
// Speaker
svg.append(rect({ x: '4mm', y: '4mm', width: '3.05cm', height: '3.05cm', ...roundBorder }));
for (let x = 0; x < 13; x++) {
for (let y = 0; y < 13; y++) {
if ((x === 0 || x === 12) && (y < 3 || y > 9) || (y === 0 || y === 12) && (x < 3 || x > 9)) {
continue;
}
svg.append(ellipse({ cx: `${8 + x * 1.9}mm`, cy: `${8 + y * 1.9}mm`, rx: '.5mm', ry: '.5mm', fill: '#333', ...stroke, ...strokeWidth }));
}
}
// Controls side speaker
svg.append(rect({ x: '35mm', y: '4mm', width: '3.05cm', height: '1.5cm', ...roundBorder }));
svg.append(ellipse({ cx: '42.5mm', cy: '11.5mm', rx: '5mm', ry: '5mm', stroke: '#aaa', ...fill, ...strokeWidth }));
svg.append(ellipse({ cx: '44.5mm', cy: '13.5mm', rx: '1mm', ry: '1mm', stroke: '#aaa', ...fill, ...strokeWidth }));
svg.append(...button(35, 19.5));
svg.append(...button(50.5, 19.5));
// Display
svg.append(rect({ x: '66.4mm', y: '4.3mm', width: '60.7mm', height: '2.98cm', rx: '1mm', stroke: '#000', 'stroke-width': '1mm', fill: '#333' }));
const displayText = element('text', { x: '96.75mm', y: '22mm', 'text-anchor': 'middle', fill: '#eee', 'font-size': '6mm', 'font-family': 'sans-serif' });
displayText.textContent = '😍 SVG OP-1 🎛️';
svg.append(displayText);
// Encoders
svg.append(...encoder(0));
svg.append(...encoder(1));
svg.append(...encoder(2));
svg.append(...encoder(3));
// Controls side encoders
svg.append(...button(252, 19.5));
svg.append(...button(252, 4));
// Row above keyboard
for (let index = 0; index < 17; index++) {
svg.append(...button(4 + index * 15.5, 35));
}
// Columns side keyboard
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
svg.append(...button(4 + x * 15.5, 50.5 + y * 15.5));
}
}
// Black keys
const dots = [10, 2.5, 2.5, 10, 2.5, 10, 2.5, 2.5, 10, 2.5];
const keys = [23, 15, 23, 23, 23, 23, 15, 23, 23, 23];
const space = .3;
for (let index = 0; index < 10; index++) {
const x = 50.5 + keys.slice(0, index).reduce((a, c) => a + c + space, 0);
const width = `${[...keys, ...keys][index] - space}mm`;
svg.append(rect({ x: `${x}mm`, y: '50.5mm', width, height: '1.5cm', ...roundBorder }));
svg.append(ellipse({ cx: `${x + 5 + dots[index]}mm`, cy: '58mm', rx: '5mm', ry: '5mm', fill: '#333', ...stroke }));
}
// White keys
for (let index = 0; index < 14; index++) {
// TODO: Add round oval shapes
svg.append(rect({ x: `${50.5 + index * 15.5}mm`, y: '66mm', width: '1.5cm', height: '3.05cm', ...roundBorder }));
svg.append(rect({ x: `${50.5 + index * 15.5 + 2.5}mm`, y: '68.5mm', width: '1cm', height: '2.5cm', rx: '5mm', stroke: '#aaa', ...fill, ...strokeWidth }));
}
// Mic
svg.append(ellipse({ cx: '275.5mm', cy: '11mm', rx: '.5mm', ry: '.5mm', fill: '#333', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '277.5mm', cy: '11mm', rx: '.5mm', ry: '.5mm', fill: '#333', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '275.5mm', cy: '13mm', rx: '.5mm', ry: '.5mm', fill: '#333', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '277.5mm', cy: '13mm', rx: '.5mm', ry: '.5mm', fill: '#333', ...stroke, ...strokeWidth }));
// Volume
svg.append(ellipse({ cx: '276.5mm', cy: '38mm', rx: '.5mm', ry: '.5mm', fill: 'red', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '276.5mm', cy: '40mm', rx: '.5mm', ry: '.5mm', fill: 'lime', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '276.5mm', cy: '42mm', rx: '.5mm', ry: '.5mm', fill: 'lime', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '276.5mm', cy: '44mm', rx: '.5mm', ry: '.5mm', fill: 'lime', ...stroke, ...strokeWidth }));
svg.append(ellipse({ cx: '276.5mm', cy: '46mm', rx: '.5mm', ry: '.5mm', fill: 'lime', ...stroke, ...strokeWidth }));
const text = element('text', { x: '27.75cm', y: '74mm', fill: '#666', 'font-size': '6mm', style: 'font-family: sans-serif; writing-mode: sideways-lr;' });
text.textContent = 'OP-1';
svg.append(text);
const downloadButton = document.getElementById('downloadButton');
downloadButton.addEventListener('click', () => {
const text = svg.outerHTML.replace('<svg', '<svg xmlns="http://www.w3.org/2000/svg"').replace(/>/g, '>\n');
const a = document.createElement('a');
a.download = 'op-1.svg';
a.href = `data:image/svg+xml,` + encodeURIComponent(text);
a.click();
});
});