This example uses two fingers to move the cursor, and a pinch motion to grab objects. Using your pointer and middle fingers like chopsticks seems to work a bit better than pinching with your thumb and pointer finger.
Last active
December 22, 2015 11:38
-
-
Save JMStewart/6466497 to your computer and use it in GitHub Desktop.
LEAP: Pinch grab
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> | |
<script src="//js.leapmotion.com/0.2.0/leap.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
</head> | |
<body> | |
<div id="canvas"> | |
<svg height="100%" width="100%"> | |
</svg> | |
</div> | |
<div id="data"></div> | |
<script> | |
var circleCount = 5; | |
var minR = 50; | |
var maxR = 150; | |
var svg = d3.select("svg"); | |
var height = svg.node().offsetHeight; | |
var width = svg.node().offsetWidth; | |
var minX = -90; | |
var maxX = 90; | |
var minY = 230; | |
var maxY = 70; | |
var xScale = d3.scale.linear() | |
.domain([minX, maxX]) | |
.range([0,width]); | |
var yScale = d3.scale.linear() | |
.domain([minY, maxY]) | |
.range([0,height]); | |
var circleGroup = svg.append("g") | |
.attr("id", "circleGroup"); | |
var crosshair = svg.append("g"); | |
crosshair.append("path") | |
.attr("d", "M-7,0h14M0,-7v14") | |
.style("stroke", "gray") | |
.attr("stroke-width", "3"); | |
var circles = []; | |
var circleIdCounter = 0; | |
function addCircle(circle){ | |
var circleBox = circle.node().getBoundingClientRect(); | |
// circles.push({ | |
// x : +circleBox.left + circleBox.width/2, | |
// y : +circleBox.top + circleBox.height/2, | |
// r : +circleBox.width/2, | |
// id : circle.attr("id") | |
// }); | |
circles.push(circle); | |
} | |
function createCircle(){ | |
var newR = Math.random() * (maxR - minR) + minR; | |
var newX = Math.random() * (width - (2 * newR)) + newR; | |
var newY = Math.random() * (height - (2 * newR)) + newR; | |
var circle = circleGroup.append("g") | |
.attr("id", "circle" + circleIdCounter) | |
.datum({}); | |
circle.selectAll("circle") | |
.data([3,2,1]) | |
.enter() | |
.append("circle") | |
.attr("cx", newX) | |
.attr("cy", newY) | |
.attr("r", "0") | |
.style("fill", function(d){return d%2 ? "red" : "white" ;}); | |
var grow = circle.transition() | |
.duration(500) | |
.each("end", function(){addCircle(d3.select(this));}); | |
grow.selectAll("circle") | |
.attr("r", function(d){ return d * newR / 3;}); | |
circleIdCounter++; | |
} | |
for(var i=0;i<circleCount;i++){ | |
createCircle(); | |
} | |
</script> | |
</body> | |
<script> | |
var pausedFrame = null; | |
var latestFrame = null; | |
var oldFrame = null; | |
var draggingCircle = null; | |
window.onkeypress = function(e) { | |
if (e.charCode == 32) { | |
if (pausedFrame == null) { | |
pausedFrame = latestFrame; | |
} else { | |
pausedFrame = null; | |
} | |
} | |
}; | |
var controller = new Leap.Controller({enableGestures: true}); | |
controller.loop(function(frame) { | |
oldFrame = latestFrame; | |
latestFrame = frame; | |
//if(!pausedFrame) | |
//document.getElementById('data').innerHTML = (pausedFrame ? "<p><b>PAUSED</b></p>" : "") + "<div>"+(pausedFrame || latestFrame).dump()+"</div>"; | |
var pointableCount = latestFrame.pointables.length; | |
var handCount = latestFrame.hands.length; | |
if(!pausedFrame && handCount == 1 && pointableCount == 2){ | |
draggingCircle = null; | |
crosshair.style("opacity", "1"); | |
var position = latestFrame.pointables[0].stabilizedTipPosition; | |
var x = xScale(position[0]); | |
var y = yScale(position[1]); | |
crosshair.attr("transform", "translate(" + x + "," + y + ")"); | |
} | |
if(!pausedFrame && oldFrame && oldFrame.pointables.length > 0 && handCount == 1 && pointableCount == 1){ | |
crosshair.style("opacity", "0"); | |
var finger = latestFrame.pointables[0]; | |
var position = finger.stabilizedTipPosition; | |
var x = xScale(position[0]); | |
var y = yScale(position[1]); | |
crosshair.attr("transform", "translate(" + x + "," + y + ")"); | |
var oldX = xScale(oldFrame.pointables[0].stabilizedTipPosition[0]); | |
var oldY = yScale(oldFrame.pointables[0].stabilizedTipPosition[1]); | |
// var oldX = xScale(oldFrame.finger(finger.id).stabilizedTipPosition[0]); | |
// var oldY = yScale(oldFrame.finger(finger.id).stabilizedTipPosition[1]); | |
if(oldFrame.pointables.length == 2){ | |
grab(x,y); | |
} | |
if(draggingCircle){ | |
draggingCircle | |
.each(function(d){ | |
console.log(d); | |
d3.select(this).selectAll("circle") | |
.attr("cx", x + d.xOffset) | |
.attr("cy", y + d.yOffset); | |
}) | |
} | |
} | |
}); | |
function grab(x,y){ | |
for(var i=0;i<circles.length;i++){ | |
var c = circles[i]; | |
// if(distance(x,y,c.x,c.y) < c.r){ | |
if(circleContainsPoint(c, x, y)){ | |
draggingCircle = c//svg.select("#"+c.id); | |
draggingCircle.each(function(d){ | |
d.xOffset = d3.select(this).select("circle").attr("cx") - x; | |
d.yOffset = d3.select(this).select("circle").attr("cy") - y; | |
console.log(d); | |
}) | |
console.log("GRAB"); | |
} | |
} | |
} | |
function circleContainsPoint(circle, x, y){ | |
var cx = circle.select("circle").attr("cx"); | |
var cy = circle.select("circle").attr("cy"); | |
var r = circle.select("circle").attr("r"); | |
console.log(distance(x,y,cx,cy) < r); | |
return distance(x,y,cx,cy) < r; | |
} | |
function distance(x1,y1,x2,y2){ | |
d = Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2)); | |
return d; | |
} | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment