git.s-ol.nu isomorphic-kb-explorer / v2
fix preset selects s-ol 4 months ago
3 changed file(s) with 72 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
22 const svg = document.getElementById('diagram');
33 const arrows = Array.from(svg.querySelectorAll('.arrow'));
44
5 const preset = panel.querySelector('.control--preset');
5 const preset = panel.querySelector('.control--preset select');
66 const controls = Array.from(panel.querySelectorAll('.control--axis'));
77 const steps = Array.from(panel.querySelectorAll('.control--axis > input'));
88 const dirs = Array.from(panel.querySelectorAll('.control--axis .dir input'));
2727 return [a, b, c, -a, -b, -c];
2828 };
2929
30 const PRESETS = {
31 'wicki-hayden': [ 7, 2, null ],
32 'janko': [ 1, 2, null ],
33 'harmonic': [ 7, 4, null ],
34 'gerhard': [ 4, 3, null ],
35 };
36
3037 const updateValues = () => {
3138 const full = completeState(state);
3239
3946 dirs[i].disabled = val == 0;
4047 }
4148 });
49
50 const presetName = Object.keys(PRESETS).find(k => completeState(PRESETS[k]).join(',') === full.join(','));
51 preset.value = presetName ?? 'custom';
52
4253 updateFocus();
4354 };
4455
94105 select(i);
95106 state[i] = +input.value;
96107 if (dirs[i].checked) state[i] = -state[i];
97 preset.value = 'custom';
98108 updateValues();
99109 };
100110 });
103113 input.onchange = () => {
104114 select(i);
105115 state[i] = state[i] * -1;
106 preset.value = 'custom';
107116 updateValues();
108117 };
109118 });
110119
111120 preset.onchange = () => {
112 switch (preset.value) {
113 case 'custom': return;
114 case 'wicki-hayden': state = [ 7, 2, null ]; break;
115 case 'janko': state = [ 1, 2, null ]; break;
116 case 'harmonic': state = [ 7, 4, null ]; break;
117 case 'gerhard': state = [ 4, 3, null ]; break;
121 const nextState = PRESETS[preset.value];
122 if (nextState) {
123 state = nextState.slice();
124 last = state.findIndex(s => s != null);
125 updateValues();
118126 }
119
120 last = state.findIndex(s => s != null);
121 updateValues();
122127 };
123128 preset.value = 'wicki-hayden';
124129 preset.onchange();
5656
5757 let lastCanvasSize = 0;
5858
59 const updateBackground = (canvasSize) => {
60 bg.strokeStyle = '#b9bdc1';
61 bg.strokeWidth = 1.5;
59 const updateForeground = (canvasSize) => {
60 fg.strokeStyle = '#b9bdc1';
61 fg.strokeWidth = 1.5;
6262
63 bg.canvas.width = bg.canvas.width;
64 bg.translate(canvasSize/2, canvasSize/2);
63 fg.canvas.width = fg.canvas.width;
64 fg.translate(canvasSize/2, canvasSize/2);
6565
6666 const rad = Math.ceil(canvasSize / size / 3);
6767 for (let q = -rad; q <= rad; q++) {
6868 const rMin = Math.max(-rad, -q-rad);
6969 const rMax = Math.min(rad, rad-q);
7070 for (let r = rMin; r <= rMax; r++) {
71 bg.save();
72 bg.translate(...hex2px([q, r]));
71 fg.save();
72 fg.translate(...hex2px([q, r]));
7373
74 hexagon(bg);
75 bg.stroke();
74 hexagon(fg);
75 fg.stroke();
7676
77 bg.restore();
77 fg.restore();
7878 }
7979 }
8080 };
9090 fg.canvas.width = fg.canvas.height = canvasSize;
9191 lastCanvasSize = canvasSize;
9292
93 updateBackground(canvasSize);
93 updateForeground(canvasSize);
9494 }
9595
96 fg.canvas.width = fg.canvas.width;
96 bg.canvas.width = bg.canvas.width;
9797
9898 layout.update();
9999
100 fg.translate(canvasSize/2, canvasSize/2);
100 bg.translate(canvasSize/2, canvasSize/2);
101101
102 fg.font = `${size*0.5}px sans-serif`;
103 fg.textAlign = 'center';
102 bg.font = `${size*0.5}px sans-serif`;
103 bg.textAlign = 'center';
104 bg.textBaseline = 'middle';
104105
105 fg.strokeStyle = '#ff0000';
106 fg.strokeWidth = 5;
107
106 bg.strokeStyle = '#ff0000';
107 bg.strokeWidth = 5;
108108
109109 const rot = layout.getRot();
110110 const [qq, rr] = layout.getSteps();
117117 const rMin = Math.max(-rad, -q-rad);
118118 const rMax = Math.min(rad, rad-q);
119119 for (let r = rMin; r <= rMax; r++) {
120 fg.save();
121 fg.translate(...hex2px([q, r]));
120 bg.save();
121 bg.translate(...hex2px([q, r]));
122122
123123 const note = q*qq + r*rr;
124124 let step = note % length;
125125 step = (step + length) % length;
126126
127127 if (steps.includes(note)) {
128 fg.fillStyle = '#eeeeee';
129 hexagon(fg);
130 fg.fill();
128 bg.fillStyle = '#eeeeee';
129 hexagon(bg);
130 bg.fill();
131131 }
132132
133 fg.rotate(-rot);
134 fg.fillStyle = '#303336';
135 fg.fillText(step, 0, size/3);
133 bg.rotate(-rot);
134 bg.fillStyle = '#303336';
135 bg.fillText(step, 0, 0);
136136
137 fg.restore();
137 bg.restore();
138138 }
139139 }
140140
141141 // const mouse = px2hex(rotate(mousePos, rot));
142 // fg.arc(...hex2px(mouse), 10, 0, 2*Math.PI);
142 // bg.arc(...hex2px(mouse), 10, 0, 2*Math.PI);
143143
144144 document.body.style.setProperty('--global-rot', `${rot}rad`);
145145 requestAnimationFrame(draw);
00 const panel = document.querySelector('aside.pattern');
11
2 const preset = panel.querySelector('.control--preset');
2 const preset = panel.querySelector('.control--preset select');
33 const patternLength = document.getElementById('pattern-len');
44 const steps = panel.querySelector('.steps');
55
66 let length = 12;
77 let pattern = [0, 2, 4, 5, 7, 9, 11];
8
9 const PRESETS = {
10 'major-7': [0, 2, 4, 5, 7, 9, 11],
11 'minor-7': [0, 2, 3, 5, 7, 8, 10],
12 'minor-harm-7': [0, 2, 3, 5, 7, 8, 11],
13 'minor-mel-7': [0, 2, 3, 5, 7, 9, 11],
14 'minor-hung-7': [0, 2, 3, 6, 7, 8, 11],
15 'penta': [0, 2, 4, 7, 9],
16 'major-3': [0, 4, 7],
17 'major-3+': [0, 4, 8],
18 'minor-3': [0, 3, 7],
19 'minor-3-': [0, 3, 6],
20 };
821
922 const update = () => {
1023 while (steps.childElementCount > length) {
2033 Array.from(steps.children).forEach((toggle, i) => {
2134 toggle.checked = pattern.includes(i);
2235 });
36
37 updatePreset();
38 };
39
40 const updatePreset = () => {
41 const presetName = Object.keys(PRESETS).find(k => PRESETS[k].join(',') === pattern.join(','));
42 preset.value = presetName ?? 'custom';
2343 };
2444
2545 patternLength.onchange = () => {
3353 Array.from(steps.children).forEach((toggle, i) => {
3454 if (toggle.checked) pattern.push(i);
3555 });
56 updatePreset();
3657 };
3758
3859 preset.onchange = (e) => {
39 const value = e.target.value;
40 switch (value) {
41 case 'custom': return;
42 case 'major-7':
43 pattern = [0, 2, 4, 5, 7, 9, 11];
44 break;
45 case 'minor-7':
46 pattern = [0, 2, 3, 5, 7, 8, 10];
47 break;
48 case 'minor-harm-7':
49 pattern = [0, 2, 3, 5, 7, 8, 11];
50 break;
51 case 'minor-mel-7':
52 pattern = [0, 2, 3, 5, 7, 9, 11];
53 break;
54 case 'minor-hung-7':
55 pattern = [0, 2, 3, 6, 7, 8, 11];
56 break;
57 case 'penta':
58 pattern = [0, 2, 4, 7, 9];
59 break;
60 case 'major-3':
61 pattern = [0, 4, 7];
62 break;
63 case 'major-3+':
64 pattern = [0, 4, 8];
65 break;
66 case 'minor-3':
67 pattern = [0, 3, 7];
68 break;
69 case 'minor-3-':
70 pattern = [0, 3, 6];
71 break;
60 const nextPattern = PRESETS[preset.value];
61 if (nextPattern) {
62 pattern = nextPattern.slice();
63 update();
7264 }
73 update();
74 preset.value = value;
7565 };
7666 preset.value = 'major-7';
77 preset.onchange({ target: preset });
67 preset.onchange();
7868
7969 export const getLength = () => length;
8070 export const getSteps = () => pattern;