Created
March 20, 2016 01:59
-
-
Save oxyflour/d04f15cec6305dfdc457 to your computer and use it in GitHub Desktop.
SaiHooker mouse gesture parser
This file contains 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> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<title>SAI HOOKER TEST</title> | |
</head> | |
<body> | |
<canvas id="c"></canvas> | |
<script> | |
Math.hypot = function(dx, dy) { | |
return Math.sqrt(dx * dx + dy * dy) | |
} | |
Math.middle = function(p1, p2) { | |
return { x:(p1.x + p2.x) / 2, y:(p1.y + p2.y) / 2 } | |
} | |
Math.diff = function(p1, p2) { | |
return { x:p1.x - p2.x, y:p1.y - p2.y } | |
} | |
function shouldReduce(pts) { | |
var begin = pts[0], | |
end = pts[pts.length - 1], | |
middle = Math.middle(begin, end), | |
diff = Math.diff(end, begin), | |
length = Math.hypot(diff.x, diff.y), | |
maxDistToLine = length * 0.14, | |
maxDistFromCenter = length * 0.52 | |
return pts.length > 2 && pts.slice(1, -1).every(pt => { | |
var dt = Math.diff(pt, begin), | |
distToLine = Math.abs(diff.y * dt.x - diff.x * dt.y) / length, | |
distToCenter = Math.hypot(middle.x - pt.x, middle.y - pt.y) | |
return distToLine < maxDistToLine && distToCenter < maxDistFromCenter | |
}) | |
} | |
function reduceLast(pts, n) { | |
var arr = pts.slice(-n), | |
begin = arr[0], | |
end = arr[arr.length - 1], | |
centerOfPosition = Math.middle(begin, end), | |
centerOfArray = arr.length > 2 ? arr[Math.floor(arr.length / 2)] : centerOfPosition, | |
middle = Math.middle(centerOfPosition, centerOfArray) | |
return shouldReduce(arr) ? | |
pts.slice(0, -n).concat(begin, middle, end) : | |
pts | |
} | |
function gestureParser() { | |
var pts = [ ], k = 2.5 | |
function toString() { | |
return this.slice(1).reduce((str, _, i) => { | |
var begin = pts[i], end = pts[i + 1], | |
slope = (end.y - begin.y) / (end.x - begin.x), | |
current = '' | |
if (slope > k || slope < -k) | |
current = end.y < begin.y ? '↑' : '↓' | |
else if (slope < 1/k && slope > -1/k) | |
current = end.x < begin.x ? '←' : '→' | |
else if (end.y < begin.y) | |
current = end.x < begin.x ? '↖' : '↗' | |
else | |
current = end.x < begin.x ? '↙' : '↘' | |
return current != str.substr(-1) ? str + current : str | |
}, '') | |
} | |
return { | |
add(x, y) { | |
pts.push({ x, y }) | |
if (pts.length >= 8) | |
pts = reduceLast(pts, 8) | |
}, | |
get() { | |
for (var n = pts.length - 1; n >= 3; n --) | |
pts = reduceLast(pts, n) | |
pts.toString = toString | |
return pts | |
}, | |
} | |
} | |
var gesture | |
function onMouseDown(e) { | |
gesture = gestureParser() | |
gesture.add(e.pageX, e.pageY) | |
dc.lastPoint = { x:e.pageX, y:e.pageY } | |
dc.clearRect(0, 0, canvas.width, canvas.height) | |
canvas.addEventListener('mousemove', onMouseMove) | |
canvas.addEventListener('mouseup', onMouseUp) | |
} | |
function onMouseMove(e) { | |
dc.beginPath() | |
dc.moveTo(dc.lastPoint.x, dc.lastPoint.y) | |
dc.lineTo(e.pageX, e.pageY) | |
dc.stroke() | |
dc.closePath() | |
dc.lastPoint = { x:e.pageX, y:e.pageY } | |
gesture.add(e.pageX, e.pageY) | |
} | |
function onMouseUp(e) { | |
dc.beginPath(); | |
var pts = gesture.get() | |
pts.forEach(function(p, i) { | |
dc.arc(p.x, p.y, 5, 0, 2*Math.PI); | |
dc.fillText(i, p.x, p.y); | |
}); | |
dc.closePath(); | |
dc.fill(); | |
dc.fillText(pts, 10, 50); | |
canvas.removeEventListener('mousemove', onMouseMove) | |
canvas.removeEventListener('mouseup', onMouseUp) | |
} | |
var body = document.body | |
body.style.margin = body.style.padding = 0 | |
body.style.overflow = 'hidden' | |
var canvas = document.getElementById('c') | |
canvas.width = window.innerWidth | |
canvas.height = window.innerHeight | |
canvas.style.background = '#eee' | |
canvas.addEventListener('mousedown', onMouseDown) | |
var dc = canvas.getContext('2d') | |
dc.font = '30px Arial' | |
dc.strokeStyle = 'rgba(0,128,255,0.5)' | |
dc.fillStyle = 'rgba(0, 0, 0, 0.5)' | |
dc.lineWidth = 3 | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment