Skip to content

Instantly share code, notes, and snippets.

@oxyflour
Created March 20, 2016 01:59
Show Gist options
  • Save oxyflour/d04f15cec6305dfdc457 to your computer and use it in GitHub Desktop.
Save oxyflour/d04f15cec6305dfdc457 to your computer and use it in GitHub Desktop.
SaiHooker mouse gesture parser
<!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