Last active
February 7, 2025 17:38
-
-
Save derekmc/08d23c4c5e0e93cdfd0dac8c2e264a41 to your computer and use it in GitHub Desktop.
chord timeline example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title> Chord Type </title> | |
<style> | |
body{ | |
font-family: sans-serif; | |
} | |
</style> | |
</head> | |
<body> | |
<h1> ChordType </h1> | |
<p> This is an in development chorded typing processor. </p> | |
<button onclick='main()'> Start </button> | |
<script src="main.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//main() | |
function page(container = document.body){ | |
container.innerHTML = ` | |
<h1> Hello, World </h1> | |
` | |
} | |
function emitChord(keylist){ | |
console.info('chord', keylist) | |
} | |
// Early release processing | |
function processTimeline({timeline, params = {earlyRelease: 15}, | |
now = Date.now(), emitter = emitChord}){ | |
let {earlyRelease} = params | |
let lastPress = 0 | |
let lastRelease = 0 | |
let pressed = {} | |
// don't modify original timeline | |
timeline = timeline.slice(0) | |
// move up release times | |
for(let i=0; i<timeline.length; ++i){ | |
let ev = timeline[i] | |
let {keyid, downup, time} = ev | |
let evtime = time | |
if(downup == "down"){ | |
pressed[keyid] = ev | |
} | |
if(downup == "up"){ | |
if(!pressed[keyid]){ | |
console.warn('keyup without keydown') | |
} else { | |
evtime = Math.max(time - earlyRelease, pressed[keyid].time + 1) | |
console.info('time up', evtime) | |
delete pressed[keyid] | |
} | |
} | |
ev.time = evtime | |
} | |
timeline.sort((x,y)=> x.time - y.time) | |
console.info('timeline sorted', timeline, earlyRelease) | |
// reset pressed keys | |
pressed = {} | |
let chordEmitted = false | |
let keylist = [] | |
// process timeline | |
for(let i=0; i<timeline.length; ++i){ | |
let ev = timeline[i] | |
let {keyid, downup, time} = ev | |
if(downup == "down"){ | |
pressed[keyid] = ev | |
chordEmitted = false | |
if(keylist.indexOf(keyid) < 0){ | |
keylist.push(keyid) | |
} | |
} | |
if(downup == "up"){ | |
console.info('keyup', keyid) | |
if(!pressed[keyid]){ | |
console.warn('keyup without keydown') | |
} else if(!chordEmitted){ | |
chordEmitted = true | |
emitter(keylist) | |
keylist = keylist.filter(x=>x!==keyid) | |
delete pressed[keyid] | |
} | |
} | |
} | |
// create "leftover" timeline, of all pressed, but not released, keys | |
let leftovers = [] | |
for(let k in pressed){ | |
leftovers.push(pressed[k]) | |
} | |
leftovers.sort((x,y)=> x.time - y.time) | |
return leftovers | |
} | |
// timelines are a sequence of keyevents that can be "batch" processed. | |
// timeline: [[keyid, "down" | "up", time]...] | |
function exampleTimeline(){ | |
let timeline = [] | |
let start = 999 | |
timeline.push({keyid: 3, downup: "down", time: start - 100}) | |
timeline.push({keyid: 1, downup: "down", time: start}) | |
timeline.push({keyid: 2, downup: "down", time: start + 100}) | |
timeline.push({keyid: 1, downup: "up", time: start + 115}) | |
timeline.push({keyid: 2, downup: "up", time: start + 500}) | |
return timeline | |
} | |
function main(){ | |
console.log('main') | |
let t1 = exampleTimeline() | |
console.log('exampleTimeline', json(t1)) | |
let t2 = processTimeline({timeline:t1}) | |
console.log('leftovers', json(t2)) | |
//let t2 = | |
page() | |
} | |
function json(x){ | |
return JSON.stringify(x) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment