-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
161 lines (140 loc) · 5.49 KB
/
index.html
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>piano-keys demo page</title>
<link rel="stylesheet" type="text/css" href="style/index.css">
</head>
<script src="dist/piano-keys.js"></script>
<body>
<div class="full-page">
<div class="section">
<div class="header">
<h1>piano-keys</h1>
<p>Lightweight piano keyboard build with Custom Elements and Canvas APIs.</p>
</div>
<piano-keys></piano-keys>
<div class="events-row">
<span id="note-display">Pressed: none</span>
<span id="hover-display">Hovered: none</span>
</div>
<h3>Layout</h3>
<div class="layout-row">
<label title="The keys layout, either 'classic' (default) or 'linear'">
layout
<select id="select-layout">
<option value="classic">classic</option>
<option value="linear">linear</option>
</select>
</label>
<label title="First key to show">
start
<input value="60" type="number" id="range-start" class="input-range" min="0" max="126" />
</label>
<label title="Last key to show. Ignored if a strictly positive 'fixed' size was provided">
end
<input value="84" type="number" id="range-end" class="input-range" min="1" max="128" />
</label>
<label title="A fixed size in pixel for a key. In 'classic' mode, it is the width of a white key.">
fixed
<input disabled value="50" type="number" id="input-fixed" class="input-range" min="20" max="200" />
<input id="checkbox-fixed" type="checkbox" />
</label>
</div>
<h3>Mouse interaction</h3>
<label title="Mouse interaction mode">
mode
<select id="select-mode">
<option value="default">default</option>
<option value="slide">slide</option>
<option value="toggle">toggle</option>
<option value="none">none</option>
</select>
</label>
<h3>Colors</h3>
<div id="colors-container"></div>
<h3>HTML</h3>
<pre><code id="code"></code></pre>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const rangeStart = document.querySelector('#range-start');
const rangeEnd = document.querySelector('#range-end');
const layoutSelect = document.querySelector('#select-layout');
const inputFixed = document.querySelector('#input-fixed');
const checkboxFixed = document.querySelector('#checkbox-fixed');
const modeSelect = document.querySelector('#select-mode');
const noteDisplay = document.querySelector('#note-display');
const hoverDisplay = document.querySelector('#hover-display');
const colorsContainer = document.querySelector('#colors-container');
const codeContainer = document.querySelector('#code');
rangeStart.addEventListener('change', () => refreshPiano());
rangeEnd.addEventListener('change', () => refreshPiano());
layoutSelect.addEventListener('change', () => refreshPiano());
inputFixed.addEventListener('change', () => refreshPiano());
checkboxFixed.addEventListener('change', () => refreshPiano());
modeSelect.addEventListener('change', () => refreshPiano());
checkboxFixed.addEventListener('input', () => {
inputFixed.disabled = ! checkboxFixed.checked;
rangeEnd.disabled = checkboxFixed.checked;
});
const pianoKeys = document.querySelector('piano-keys');
pianoKeys.addEventListener('keychange', () => {
const notes = pianoKeys.pressedKeys.length === 0 ?
'none' : pianoKeys.pressedKeys.map(key => midiNoteName(key)).join(', ');
noteDisplay.innerText = `Pressed: ${notes}`;
});
pianoKeys.addEventListener('keyhover', () => {
const note = midiNoteName(pianoKeys.hoveredKey);
hoverDisplay.innerText = `Hovered: ${note}`;
});
function refreshPiano() {
pianoKeys.start = rangeStart.value;
pianoKeys.end = rangeEnd.value;
pianoKeys.layout = layoutSelect.value;
pianoKeys.fixed = checkboxFixed.checked ? inputFixed.value : 0;
pianoKeys.mode = modeSelect.value;
codeContainer.innerText = pianoKeys.outerHTML;
}
function midiNoteName(noteNumber) {
if (noteNumber == null) {
return 'none'
}
const pitchNames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
const pitch = noteNumber % 12;
const octave = Math.floor(noteNumber / 12) - 2;
return pitchNames[pitch] + octave.toFixed(0);
}
prepareColorPicker('whiteKey', '#ffffff');
prepareColorPicker('whiteKeyHover', '#eeeeee');
prepareColorPicker('whiteKeyOn', '#cccccc');
prepareColorPicker('blackKey', '#888888');
prepareColorPicker('blackKeyHover', '#333333');
prepareColorPicker('blackKeyOn', '#111111');
prepareColorPicker('stroke', '#00000');
function prepareColorPicker(attributeName, defaultValue) {
const colorPicker = document.createElement('input');
colorPicker.type = 'color';
colorPicker.value = defaultValue;
const label = document.createElement('label');
const span = document.createElement('span');
span.innerText = attributeName;
label.append(colorPicker, span);
colorPicker.addEventListener('change', () => {
pianoKeys[attributeName] = colorPicker.value;
refreshPiano();
});
colorsContainer.append(label);
}
refreshPiano();
});
</script>
<div class="github-link">
<a href="https://github.com/pckerneis/piano-keys">
View on GitHub
</a>
</div>
</body>
</html>