v2.4 : choix du clavier azerty ou qwerty
This commit is contained in:
+69
-9
@@ -136,7 +136,18 @@
|
||||
}
|
||||
.bkey:active,.bkey.pressed{background:#3A362C}
|
||||
.bkey.outkey{background:#4B4739}
|
||||
.kbd-hint{font-size:.55rem;color:var(--silk-light);opacity:.4;margin-top:.5rem;letter-spacing:.08em}
|
||||
.kbd-hint{font-size:.55rem;color:var(--silk-light);opacity:.4;letter-spacing:.08em}
|
||||
.kbd-foot{display:flex;align-items:center;justify-content:space-between;gap:.6rem;margin-top:.5rem;flex-wrap:wrap}
|
||||
.seg{display:inline-flex;border:1px solid #4A4436;border-radius:6px;overflow:hidden;flex:none}
|
||||
.segbtn{
|
||||
background:var(--module-2);border:none;
|
||||
color:var(--silk-light);font-family:var(--mono);
|
||||
font-size:.55rem;letter-spacing:.1em;
|
||||
padding:.28rem .5rem;cursor:pointer;opacity:.5;
|
||||
}
|
||||
.segbtn + .segbtn{border-left:1px solid #4A4436}
|
||||
.segbtn.on{background:#4A4436;color:var(--led-on);opacity:1}
|
||||
.segbtn:focus-visible{outline:2px solid var(--led-on);outline-offset:-2px}
|
||||
|
||||
/* ---------- Colonne voicing ---------- */
|
||||
.side{display:flex;flex-direction:column;gap:.65rem}
|
||||
@@ -220,6 +231,15 @@
|
||||
}
|
||||
|
||||
footer{margin-top:1rem;font-size:.55rem;opacity:.5;letter-spacing:.1em;text-align:right}
|
||||
footer .doclink{
|
||||
color:var(--silk);text-decoration:none;
|
||||
border-bottom:1px solid rgba(64,58,47,.45);
|
||||
padding-bottom:1px;
|
||||
}
|
||||
footer .doclink:hover,footer .doclink:focus-visible{
|
||||
color:var(--accent);border-bottom-color:var(--accent);outline:none;
|
||||
}
|
||||
footer .docsep{margin:0 .35rem;opacity:.5}
|
||||
|
||||
@media (max-width:900px){
|
||||
.deck{grid-template-columns:1fr}
|
||||
@@ -234,7 +254,7 @@
|
||||
<body>
|
||||
<div class="unit">
|
||||
<header>
|
||||
<h1><span>_chordlab.v2</span></h1>
|
||||
<h1>_chordlab <span>ORC·v2</span></h1>
|
||||
<div class="sub">chord ideas machine · underscorelab / leradiologue</div>
|
||||
</header>
|
||||
|
||||
@@ -291,7 +311,12 @@
|
||||
<div class="mod kbd-mod">
|
||||
<h2>Root</h2>
|
||||
<div class="kbd" id="kbd"></div>
|
||||
<div class="kbd-hint">clavier PC : A W S E D F T G Y H U J · ␣ = ADD · ← → = voicing</div>
|
||||
<div class="kbd-foot">
|
||||
<span class="kbd-hint" id="kbdHint">clavier PC : A W S E D F T G Y H U J · ␣ = ADD · ← → = voicing</span>
|
||||
<span class="seg" role="group" aria-label="Disposition du clavier">
|
||||
<button class="segbtn" id="layQwerty" aria-pressed="false">QWERTY</button><button class="segbtn on" id="layAzerty" aria-pressed="true">AZERTY</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Voicing / drop / slash / bass / key -->
|
||||
@@ -435,7 +460,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>_chordlab v2.3 · logique d'accords</footer>
|
||||
<footer>
|
||||
<a href="tuto.html" class="doclink">Manuel (FR)</a>
|
||||
<span class="docsep">·</span>
|
||||
<a href="tuto_en.html" class="doclink">Manual (EN)</a>
|
||||
<span class="docsep">·</span>
|
||||
_chordlab v2.4 · underscorelab / leradiologue
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -466,6 +497,7 @@ const state = {
|
||||
vlAuto:false,
|
||||
perf:"block", rate:0.25,
|
||||
humanize:false,
|
||||
layout:(navigator.language||"").toLowerCase().startsWith("fr") ? "azerty" : "qwerty",
|
||||
};
|
||||
|
||||
/* ---------- Moteur d'accords ---------- */
|
||||
@@ -875,6 +907,7 @@ function saveSession(){
|
||||
drop:state.drop, slash:state.slash, bass:state.bass, bassOct:state.bassOct,
|
||||
keyMode:state.keyMode, keyRoot:state.keyRoot, keyScale:state.keyScale,
|
||||
perf:state.perf, rate:state.rate, humanize:state.humanize,
|
||||
layout:state.layout,
|
||||
bpm:getBpm(), vlAuto:state.vlAuto,
|
||||
},
|
||||
progression:state.progression,
|
||||
@@ -905,6 +938,7 @@ function loadSession(file){
|
||||
state.perf=s.perf||"block";
|
||||
state.rate=s.rate||0.25;
|
||||
state.humanize=!!s.humanize;
|
||||
state.layout=(s.layout==="qwerty")?"qwerty":(s.layout==="azerty"?"azerty":state.layout);
|
||||
state.vlAuto=!!s.vlAuto;
|
||||
state.progression=Array.isArray(d.progression)?d.progression:[];
|
||||
state.progression.forEach(c=>{ c.beats=Math.max(1,Math.min(16,c.beats||4)); });
|
||||
@@ -927,6 +961,7 @@ function syncUiFromState(){
|
||||
$("keyScaleSel").value=state.keyScale;
|
||||
$("perfSel").value=state.perf; $("rateSel").value=state.rate;
|
||||
$("humanBtn").classList.toggle("on", state.humanize);
|
||||
setLayout(state.layout);
|
||||
$("vlBtn").classList.toggle("on", state.vlAuto);
|
||||
$("lcdDrop").textContent=state.drop.toUpperCase();
|
||||
$("lcdPerf").textContent=$("perfSel").selectedOptions[0].textContent.toUpperCase();
|
||||
@@ -1006,21 +1041,45 @@ kbdEl.addEventListener("pointerdown",ev=>{
|
||||
kbdEl.addEventListener("pointerup",ev=>{
|
||||
ev.target.classList&&ev.target.classList.remove("pressed");
|
||||
});
|
||||
const PCKEYS={a:0,w:1,s:2,e:3,d:4,f:5,t:6,g:7,y:8,h:9,u:10,j:11};
|
||||
/* Dispositions clavier : mêmes touches physiques, lettres différentes.
|
||||
Sur AZERTY, A→Q et W→Z ; le reste de la rangée est identique. */
|
||||
const KEYMAPS = {
|
||||
qwerty:{a:0,w:1,s:2,e:3,d:4,f:5,t:6,g:7,y:8,h:9,u:10,j:11},
|
||||
azerty:{q:0,z:1,s:2,e:3,d:4,f:5,t:6,g:7,y:8,h:9,u:10,j:11},
|
||||
};
|
||||
const KEYHINT = {
|
||||
qwerty:"clavier PC : A W S E D F T G Y H U J · ␣ = ADD · ← → = voicing",
|
||||
azerty:"clavier PC : Q Z S E D F T G Y H U J · ␣ = ADD · ← → = voicing",
|
||||
};
|
||||
function pcKeys(){ return KEYMAPS[state.layout]; }
|
||||
function setLayout(l, silent){
|
||||
state.layout = (l==="qwerty") ? "qwerty" : "azerty";
|
||||
const isQ = state.layout==="qwerty";
|
||||
$("layQwerty").classList.toggle("on", isQ);
|
||||
$("layAzerty").classList.toggle("on", !isQ);
|
||||
$("layQwerty").setAttribute("aria-pressed", isQ);
|
||||
$("layAzerty").setAttribute("aria-pressed", !isQ);
|
||||
$("kbdHint").textContent = KEYHINT[state.layout];
|
||||
}
|
||||
|
||||
window.addEventListener("keydown",ev=>{
|
||||
if (ev.repeat||ev.target.tagName==="INPUT"||ev.target.tagName==="SELECT") return;
|
||||
const k=ev.key.toLowerCase();
|
||||
if (k in PCKEYS){
|
||||
keyEls[PCKEYS[k]].classList.add("pressed");
|
||||
triggerChord(PCKEYS[k]);
|
||||
const map=pcKeys();
|
||||
if (k in map){
|
||||
keyEls[map[k]].classList.add("pressed");
|
||||
triggerChord(map[k]);
|
||||
} else if (ev.code==="Space"){ ev.preventDefault(); addToProgression(); }
|
||||
else if (ev.key==="ArrowRight"){ setVoicing(state.voicing+1); }
|
||||
else if (ev.key==="ArrowLeft"){ setVoicing(state.voicing-1); }
|
||||
});
|
||||
window.addEventListener("keyup",ev=>{
|
||||
const k=ev.key.toLowerCase();
|
||||
if (k in PCKEYS) keyEls[PCKEYS[k]].classList.remove("pressed");
|
||||
const map=pcKeys();
|
||||
if (k in map) keyEls[map[k]].classList.remove("pressed");
|
||||
});
|
||||
$("layQwerty").addEventListener("click",()=>setLayout("qwerty"));
|
||||
$("layAzerty").addEventListener("click",()=>setLayout("azerty"));
|
||||
|
||||
/* knob voicing */
|
||||
const knob=$("voicingKnob");
|
||||
@@ -1270,6 +1329,7 @@ $("fileInput").addEventListener("change",function(){
|
||||
|
||||
/* init */
|
||||
buildKeyboard();
|
||||
setLayout(state.layout);
|
||||
renderProgression();
|
||||
refreshKeyDimming();
|
||||
setVoicing(0,true);
|
||||
|
||||
Reference in New Issue
Block a user