Created
August 31, 2015 14:24
-
-
Save skokenes/fd6b142c0f38e71424ab to your computer and use it in GitHub Desktop.
Scatterplot with Lasso on points
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
sepalLength | sepalWidth | petalLength | petalWidth | species | |
---|---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa | |
4.9 | 3.0 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.3 | 0.2 | setosa | |
4.6 | 3.1 | 1.5 | 0.2 | setosa | |
5.0 | 3.6 | 1.4 | 0.2 | setosa | |
5.4 | 3.9 | 1.7 | 0.4 | setosa | |
4.6 | 3.4 | 1.4 | 0.3 | setosa | |
5.0 | 3.4 | 1.5 | 0.2 | setosa | |
4.4 | 2.9 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.1 | setosa | |
5.4 | 3.7 | 1.5 | 0.2 | setosa | |
4.8 | 3.4 | 1.6 | 0.2 | setosa | |
4.8 | 3.0 | 1.4 | 0.1 | setosa | |
4.3 | 3.0 | 1.1 | 0.1 | setosa | |
5.8 | 4.0 | 1.2 | 0.2 | setosa | |
5.7 | 4.4 | 1.5 | 0.4 | setosa | |
5.4 | 3.9 | 1.3 | 0.4 | setosa | |
5.1 | 3.5 | 1.4 | 0.3 | setosa | |
5.7 | 3.8 | 1.7 | 0.3 | setosa | |
5.1 | 3.8 | 1.5 | 0.3 | setosa | |
5.4 | 3.4 | 1.7 | 0.2 | setosa | |
5.1 | 3.7 | 1.5 | 0.4 | setosa | |
4.6 | 3.6 | 1.0 | 0.2 | setosa | |
5.1 | 3.3 | 1.7 | 0.5 | setosa | |
4.8 | 3.4 | 1.9 | 0.2 | setosa | |
5.0 | 3.0 | 1.6 | 0.2 | setosa | |
5.0 | 3.4 | 1.6 | 0.4 | setosa | |
5.2 | 3.5 | 1.5 | 0.2 | setosa | |
5.2 | 3.4 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.6 | 0.2 | setosa | |
4.8 | 3.1 | 1.6 | 0.2 | setosa | |
5.4 | 3.4 | 1.5 | 0.4 | setosa | |
5.2 | 4.1 | 1.5 | 0.1 | setosa | |
5.5 | 4.2 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.2 | setosa | |
5.0 | 3.2 | 1.2 | 0.2 | setosa | |
5.5 | 3.5 | 1.3 | 0.2 | setosa | |
4.9 | 3.6 | 1.4 | 0.1 | setosa | |
4.4 | 3.0 | 1.3 | 0.2 | setosa | |
5.1 | 3.4 | 1.5 | 0.2 | setosa | |
5.0 | 3.5 | 1.3 | 0.3 | setosa | |
4.5 | 2.3 | 1.3 | 0.3 | setosa | |
4.4 | 3.2 | 1.3 | 0.2 | setosa | |
5.0 | 3.5 | 1.6 | 0.6 | setosa | |
5.1 | 3.8 | 1.9 | 0.4 | setosa | |
4.8 | 3.0 | 1.4 | 0.3 | setosa | |
5.1 | 3.8 | 1.6 | 0.2 | setosa | |
4.6 | 3.2 | 1.4 | 0.2 | setosa | |
5.3 | 3.7 | 1.5 | 0.2 | setosa | |
5.0 | 3.3 | 1.4 | 0.2 | setosa | |
7.0 | 3.2 | 4.7 | 1.4 | versicolor | |
6.4 | 3.2 | 4.5 | 1.5 | versicolor | |
6.9 | 3.1 | 4.9 | 1.5 | versicolor | |
5.5 | 2.3 | 4.0 | 1.3 | versicolor | |
6.5 | 2.8 | 4.6 | 1.5 | versicolor | |
5.7 | 2.8 | 4.5 | 1.3 | versicolor | |
6.3 | 3.3 | 4.7 | 1.6 | versicolor | |
4.9 | 2.4 | 3.3 | 1.0 | versicolor | |
6.6 | 2.9 | 4.6 | 1.3 | versicolor | |
5.2 | 2.7 | 3.9 | 1.4 | versicolor | |
5.0 | 2.0 | 3.5 | 1.0 | versicolor | |
5.9 | 3.0 | 4.2 | 1.5 | versicolor | |
6.0 | 2.2 | 4.0 | 1.0 | versicolor | |
6.1 | 2.9 | 4.7 | 1.4 | versicolor | |
5.6 | 2.9 | 3.6 | 1.3 | versicolor | |
6.7 | 3.1 | 4.4 | 1.4 | versicolor | |
5.6 | 3.0 | 4.5 | 1.5 | versicolor | |
5.8 | 2.7 | 4.1 | 1.0 | versicolor | |
6.2 | 2.2 | 4.5 | 1.5 | versicolor | |
5.6 | 2.5 | 3.9 | 1.1 | versicolor | |
5.9 | 3.2 | 4.8 | 1.8 | versicolor | |
6.1 | 2.8 | 4.0 | 1.3 | versicolor | |
6.3 | 2.5 | 4.9 | 1.5 | versicolor | |
6.1 | 2.8 | 4.7 | 1.2 | versicolor | |
6.4 | 2.9 | 4.3 | 1.3 | versicolor | |
6.6 | 3.0 | 4.4 | 1.4 | versicolor | |
6.8 | 2.8 | 4.8 | 1.4 | versicolor | |
6.7 | 3.0 | 5.0 | 1.7 | versicolor | |
6.0 | 2.9 | 4.5 | 1.5 | versicolor | |
5.7 | 2.6 | 3.5 | 1.0 | versicolor | |
5.5 | 2.4 | 3.8 | 1.1 | versicolor | |
5.5 | 2.4 | 3.7 | 1.0 | versicolor | |
5.8 | 2.7 | 3.9 | 1.2 | versicolor | |
6.0 | 2.7 | 5.1 | 1.6 | versicolor | |
5.4 | 3.0 | 4.5 | 1.5 | versicolor | |
6.0 | 3.4 | 4.5 | 1.6 | versicolor | |
6.7 | 3.1 | 4.7 | 1.5 | versicolor | |
6.3 | 2.3 | 4.4 | 1.3 | versicolor | |
5.6 | 3.0 | 4.1 | 1.3 | versicolor | |
5.5 | 2.5 | 4.0 | 1.3 | versicolor | |
5.5 | 2.6 | 4.4 | 1.2 | versicolor | |
6.1 | 3.0 | 4.6 | 1.4 | versicolor | |
5.8 | 2.6 | 4.0 | 1.2 | versicolor | |
5.0 | 2.3 | 3.3 | 1.0 | versicolor | |
5.6 | 2.7 | 4.2 | 1.3 | versicolor | |
5.7 | 3.0 | 4.2 | 1.2 | versicolor | |
5.7 | 2.9 | 4.2 | 1.3 | versicolor | |
6.2 | 2.9 | 4.3 | 1.3 | versicolor | |
5.1 | 2.5 | 3.0 | 1.1 | versicolor | |
5.7 | 2.8 | 4.1 | 1.3 | versicolor | |
6.3 | 3.3 | 6.0 | 2.5 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
7.1 | 3.0 | 5.9 | 2.1 | virginica | |
6.3 | 2.9 | 5.6 | 1.8 | virginica | |
6.5 | 3.0 | 5.8 | 2.2 | virginica | |
7.6 | 3.0 | 6.6 | 2.1 | virginica | |
4.9 | 2.5 | 4.5 | 1.7 | virginica | |
7.3 | 2.9 | 6.3 | 1.8 | virginica | |
6.7 | 2.5 | 5.8 | 1.8 | virginica | |
7.2 | 3.6 | 6.1 | 2.5 | virginica | |
6.5 | 3.2 | 5.1 | 2.0 | virginica | |
6.4 | 2.7 | 5.3 | 1.9 | virginica | |
6.8 | 3.0 | 5.5 | 2.1 | virginica | |
5.7 | 2.5 | 5.0 | 2.0 | virginica | |
5.8 | 2.8 | 5.1 | 2.4 | virginica | |
6.4 | 3.2 | 5.3 | 2.3 | virginica | |
6.5 | 3.0 | 5.5 | 1.8 | virginica | |
7.7 | 3.8 | 6.7 | 2.2 | virginica | |
7.7 | 2.6 | 6.9 | 2.3 | virginica | |
6.0 | 2.2 | 5.0 | 1.5 | virginica | |
6.9 | 3.2 | 5.7 | 2.3 | virginica | |
5.6 | 2.8 | 4.9 | 2.0 | virginica | |
7.7 | 2.8 | 6.7 | 2.0 | virginica | |
6.3 | 2.7 | 4.9 | 1.8 | virginica | |
6.7 | 3.3 | 5.7 | 2.1 | virginica | |
7.2 | 3.2 | 6.0 | 1.8 | virginica | |
6.2 | 2.8 | 4.8 | 1.8 | virginica | |
6.1 | 3.0 | 4.9 | 1.8 | virginica | |
6.4 | 2.8 | 5.6 | 2.1 | virginica | |
7.2 | 3.0 | 5.8 | 1.6 | virginica | |
7.4 | 2.8 | 6.1 | 1.9 | virginica | |
7.9 | 3.8 | 6.4 | 2.0 | virginica | |
6.4 | 2.8 | 5.6 | 2.2 | virginica | |
6.3 | 2.8 | 5.1 | 1.5 | virginica | |
6.1 | 2.6 | 5.6 | 1.4 | virginica | |
7.7 | 3.0 | 6.1 | 2.3 | virginica | |
6.3 | 3.4 | 5.6 | 2.4 | virginica | |
6.4 | 3.1 | 5.5 | 1.8 | virginica | |
6.0 | 3.0 | 4.8 | 1.8 | virginica | |
6.9 | 3.1 | 5.4 | 2.1 | virginica | |
6.7 | 3.1 | 5.6 | 2.4 | virginica | |
6.9 | 3.1 | 5.1 | 2.3 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
6.8 | 3.2 | 5.9 | 2.3 | virginica | |
6.7 | 3.3 | 5.7 | 2.5 | virginica | |
6.7 | 3.0 | 5.2 | 2.3 | virginica | |
6.3 | 2.5 | 5.0 | 1.9 | virginica | |
6.5 | 3.0 | 5.2 | 2.0 | virginica | |
6.2 | 3.4 | 5.4 | 2.3 | virginica | |
5.9 | 3.0 | 5.1 | 1.8 | virginica |
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> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.dot { | |
stroke: #000; | |
} | |
.lasso path { | |
stroke: rgb(80,80,80); | |
stroke-width:2px; | |
} | |
.lasso .drawn { | |
fill-opacity:.05 ; | |
} | |
.lasso .loop_close { | |
fill:none; | |
stroke-dasharray: 4,4; | |
} | |
.lasso .origin { | |
fill:#3399FF; | |
fill-opacity:.5; | |
} | |
.not_possible { | |
fill:rgb(200,200,200); | |
} | |
.possible { | |
fill:#EC888C; | |
} | |
svg { | |
margin-left: 30px; | |
margin-top: 30px; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src = "lasso.js"></script> | |
<script> | |
var margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var x = d3.scale.linear() | |
.range([0, width]); | |
var y = d3.scale.linear() | |
.range([height, 0]); | |
var color = d3.scale.category10(); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom"); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left"); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// Create the area where the lasso event can be triggered | |
svg.append("rect") | |
.attr('class','lassoable') | |
.attr("width",width) | |
.attr("height",height) | |
.style("opacity",0); | |
// Lasso functions to execute while lassoing | |
var lasso_start = function() { | |
lasso.items() | |
.attr("r",3.5) // reset size | |
.style("fill",null) // clear all of the fills | |
.classed({"not_possible":true,"selected":false}); // style as not possible | |
}; | |
var lasso_draw = function() { | |
// Style the possible dots | |
lasso.items().filter(function(d) {return d.possible===true}) | |
.classed({"not_possible":false,"possible":true}); | |
// Style the not possible dot | |
lasso.items().filter(function(d) {return d.possible===false}) | |
.classed({"not_possible":true,"possible":false}); | |
}; | |
var lasso_end = function() { | |
// Reset the color of all dots | |
lasso.items() | |
.style("fill", function(d) { return color(d.species); }); | |
// Style the selected dots | |
lasso.items().filter(function(d) {return d.selected===true}) | |
.classed({"not_possible":false,"possible":false}) | |
.attr("r",7); | |
// Reset the style of the not selected dots | |
lasso.items().filter(function(d) {return d.selected===false}) | |
.classed({"not_possible":false,"possible":false}) | |
.attr("r",3.5); | |
}; | |
// Define the lasso | |
var lasso = d3.lasso() | |
.closePathDistance(75) // max distance for the lasso loop to be closed | |
.closePathSelect(true) // can items be selected by closing the path? | |
.hoverSelect(true) // can items by selected by hovering over them? | |
.on("start",lasso_start) // lasso start function | |
.on("draw",lasso_draw) // lasso draw function | |
.on("end",lasso_end); // lasso end function | |
d3.tsv("data.tsv", function(error, data) { | |
data.forEach(function(d) { | |
d.sepalLength = +d.sepalLength; | |
d.sepalWidth = +d.sepalWidth; | |
}); | |
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice(); | |
y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice(); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis) | |
.append("text") | |
.attr("class", "label") | |
.attr("x", width) | |
.attr("y", -6) | |
.style("text-anchor", "end") | |
.text("Sepal Width (cm)"); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("class", "label") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.text("Sepal Length (cm)") | |
var dot_g = svg.append('g') | |
.attr('class','lassoable'); | |
dot_g.selectAll(".dot") | |
.data(data) | |
.enter().append("circle") | |
.attr("id",function(d,i) {return "dot_" + i;}) // added | |
.attr("class", "dot") | |
.attr("r", 3.5) | |
.attr("cx", function(d) { return x(d.sepalWidth); }) | |
.attr("cy", function(d) { return y(d.sepalLength); }) | |
.style("fill", function(d) { return color(d.species); }); | |
lasso.items(d3.selectAll(".dot")); | |
//lasso.items(d3.selectAll("#dot_118")); | |
var legend = svg.selectAll(".legend") | |
.data(color.domain()) | |
.enter().append("g") | |
.attr("class", "legend") | |
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); | |
legend.append("rect") | |
.attr("x", width - 18) | |
.attr("width", 18) | |
.attr("height", 18) | |
.style("fill", color); | |
legend.append("text") | |
.attr("x", width - 24) | |
.attr("y", 9) | |
.attr("dy", ".35em") | |
.style("text-anchor", "end") | |
.text(function(d) { return d; }); | |
lasso.area(svg.selectAll('.lassoable')); | |
// Init the lasso on the svg:g that contains the dots | |
svg.call(lasso); | |
}); | |
</script> |
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
d3.lasso = function() { | |
var items = null, | |
closePathDistance = 75, | |
closePathSelect = true, | |
isPathClosed = false, | |
hoverSelect = true, | |
points = [], | |
area = null, | |
on = {start:function(){}, draw: function(){}, end: function(){}}; | |
function lasso() { | |
var _this = d3.select(this[0][0]); | |
var body = d3.select('body'); | |
var svg = d3.select('svg'); | |
var g = _this.append("g") | |
.attr("class","lasso"); | |
var dyn_path = g.append("path") | |
.attr("class","drawn"); | |
var calc_path = g.append("path") | |
.attr("display","none"); | |
var close_path = g.append("path") | |
.attr("class","loop_close"); | |
var complete_path = g.append("path") | |
.attr("display","none"); | |
var origin_node = g.append("circle") | |
.attr("class","origin"); | |
var path; | |
var tpath; | |
var origin; | |
var torigin; | |
var last_known_point; | |
var path_length_start; | |
var drag = d3.behavior.drag() | |
.on("dragstart",dragstart) | |
.on("drag",dragmove) | |
.on("dragend",dragend); | |
area.call(drag); | |
function dragstart() { | |
// Reset blank lasso path | |
path=""; | |
tpath = ""; | |
dyn_path.attr("d",null); | |
close_path.attr("d",null); | |
// Set path length start | |
path_length_start = 0; | |
var offset_box = _this[0][0].getBoundingClientRect(); | |
// Set every item to have a false selection and reset their center point and counters | |
items[0].forEach(function(d) { | |
d.hoverSelected = false; | |
d.loopSelected = false; | |
var cur_box = d.getBBox(); | |
var new_box = d.getBoundingClientRect(); // relative to body! use this instead of the other formulas that calculate offsets and what not | |
d.lassoPoint = { | |
//cx: Math.round(new_box.left-offset_box.left + new_box.width/2), | |
cx: Math.round(new_box.left + new_box.width/2), | |
//cy: Math.round(new_box.top-offset_box.top + new_box.height/2), | |
cy: Math.round(new_box.top + new_box.height/2), | |
edges: {top:0,right:0,bottom:0,left:0}, | |
close_edges: {left: 0, right: 0} | |
}; | |
}); | |
// if hover is on, add hover function | |
if(hoverSelect===true) { | |
items.on("mouseover.lasso",function() { | |
// if hovered, change lasso selection attribute to true | |
d3.select(this)[0][0].hoverSelected = true; | |
}); | |
} | |
// Run user defined start function | |
on.start(); | |
} | |
function dragmove() { | |
// GET MOUSE POSITION WITHIN BODY / WINDOW | |
//console.log(d3.event); | |
var x = d3.event.sourceEvent.clientX;//d3.mouse(this)[0]; | |
var y = d3.event.sourceEvent.clientY;//d3.mouse(this)[1]; | |
var tx = d3.mouse(this)[0]; | |
var ty = d3.mouse(this)[1]; | |
// Initialize the path or add the latest point to it | |
if (path=="") { | |
path = path + "M " + x + " " + y; | |
tpath = tpath + "M " + tx + " " + ty; | |
origin = [x,y]; | |
torigin = [tx,ty]; | |
// Draw origin node | |
origin_node | |
.attr("cx",tx) | |
.attr("cy",ty) | |
.attr("r",7) | |
.attr("display",null); | |
} | |
else { | |
path = path + " L " + x + " " + y; | |
tpath = tpath + " L " + tx + " " + ty; | |
} | |
// Reset closed edges counter | |
items[0].forEach(function(d) { | |
d.lassoPoint.close_edges = {left:0,right:0}; | |
}); | |
// Calculate the current distance from the lasso origin | |
var distance = Math.sqrt(Math.pow(x-origin[0],2)+Math.pow(y-origin[1],2)); | |
// Set the closed path line | |
var close_draw_path = "M " + tx + " " + ty + " L " + torigin[0] + " " + torigin[1]; | |
// Draw the lines | |
dyn_path.attr("d",tpath); | |
// path for calcs | |
calc_path.attr("d",path); | |
// If within the closed path distance parameter, show the closed path. otherwise, hide it | |
if(distance<=closePathDistance) { | |
close_path.attr("display",null); | |
} | |
else { | |
close_path.attr("display","none"); | |
} | |
isPathClosed = distance<=closePathDistance ? true : false; | |
// create complete path | |
var complete_path_d = path + "Z"; | |
complete_path.attr("d",complete_path_d); | |
// get path length | |
var path_node = calc_path.node(); | |
var path_length_end = path_node.getTotalLength(); | |
var last_pos = path_node.getPointAtLength(path_length_start-1); | |
for (var i = path_length_start; i<=path_length_end; i++) { | |
var cur_pos = path_node.getPointAtLength(i); | |
var cur_pos_obj = { | |
x:Math.round(cur_pos.x*100)/100, | |
y:Math.round(cur_pos.y*100)/100, | |
}; | |
var prior_pos = path_node.getPointAtLength(i-1); | |
var prior_pos_obj = { | |
x:Math.round(prior_pos.x*100)/100, | |
y:Math.round(prior_pos.y*100)/100, | |
}; | |
items[0].filter(function(d) { | |
var a; | |
if(d.lassoPoint.cy === cur_pos_obj.y && d.lassoPoint.cy != prior_pos_obj.y) { | |
last_known_point = { | |
x: prior_pos_obj.x, | |
y: prior_pos_obj.y | |
}; | |
a=false; | |
} | |
else if (d.lassoPoint.cy === cur_pos_obj.y && d.lassoPoint.cy === prior_pos_obj.y) { | |
a = false; | |
} | |
else if (d.lassoPoint.cy === prior_pos_obj.y && d.lassoPoint.cy != cur_pos_obj.y) { | |
a = sign(d.lassoPoint.cy-cur_pos_obj.y)!=sign(d.lassoPoint.cy-last_known_point.y); | |
} | |
else { | |
last_known_point = { | |
x: prior_pos_obj.x, | |
y: prior_pos_obj.y | |
}; | |
a = sign(d.lassoPoint.cy-cur_pos_obj.y)!=sign(d.lassoPoint.cy-prior_pos_obj.y); | |
} | |
return a; | |
}).forEach(function(d) { | |
if(cur_pos_obj.x>d.lassoPoint.cx) { | |
d.lassoPoint.edges.right = d.lassoPoint.edges.right+1; | |
} | |
if(cur_pos_obj.x<d.lassoPoint.cx) { | |
d.lassoPoint.edges.left = d.lassoPoint.edges.left+1; | |
} | |
}); | |
} | |
if(isPathClosed == true && closePathSelect == true) { | |
close_path.attr("d",close_draw_path); | |
close_path_node =close_path.node(); | |
var close_path_length = close_path_node.getTotalLength(); | |
var close_path_edges = {left:0,right:0}; | |
for (var i = 0; i<=close_path_length; i++) { | |
var cur_pos = close_path_node.getPointAtLength(i); | |
var prior_pos = close_path_node.getPointAtLength(i-1); | |
items[0].filter(function(d) {return d.lassoPoint.cy==Math.round(cur_pos.y)}).forEach(function(d) { | |
if(Math.round(cur_pos.y)!=Math.round(prior_pos.y) && Math.round(cur_pos.x)>d.lassoPoint.cx) { | |
d.lassoPoint.close_edges.right = 1; | |
} | |
if(Math.round(cur_pos.y)!=Math.round(prior_pos.y) && Math.round(cur_pos.x)<d.lassoPoint.cx) { | |
d.lassoPoint.close_edges.left = 1; | |
} | |
}); | |
} | |
items[0].forEach(function(a) { | |
if((a.lassoPoint.edges.left+a.lassoPoint.close_edges.left)>0 && (a.lassoPoint.edges.right + a.lassoPoint.close_edges.right)%2 ==1) { | |
a.loopSelected = true; | |
} | |
else { | |
a.loopSelected = false; | |
} | |
}); | |
} | |
else { | |
items[0].forEach(function(d) { | |
d.loopSelected = false; | |
}) | |
} | |
// Tag possible items | |
d3.selectAll(items[0].filter(function(d) {return (d.loopSelected && isPathClosed) || d.hoverSelected})) | |
.each(function(d) { d.possible = true;}); | |
//.attr("d",function(d) {return d.possible = true;}); | |
d3.selectAll(items[0].filter(function(d) {return !((d.loopSelected && isPathClosed) || d.hoverSelected)})) | |
.each(function(d) {d.possible = false;}); | |
//.attr("d",function(d) {return d.possible = false;}); | |
on.draw(); | |
// Continue drawing path from where it left off | |
path_length_start = path_length_end+1; | |
} | |
function dragend() { | |
// Remove mouseover tagging function | |
items.on("mouseover.lasso",null); | |
// Tag selected items | |
items.filter(function(d) {return d.possible === true}) | |
.each(function(d) {d.selected = true;}); | |
//.attr("d",function(d) {return d.selected = true;}); | |
items.filter(function(d) {return d.possible === false}) | |
.each(function(d) {d.selected = false;}); | |
//.attr("d",function(d) {return d.selected = false;}); | |
// Reset possible items | |
items | |
.each(function(d) {d.possible = false;}); | |
//.attr("d",function(d) {return d.possible = false}); | |
// Clear lasso | |
dyn_path.attr("d",null); | |
close_path.attr("d",null); | |
origin_node.attr("display","none"); | |
// Run user defined end function | |
on.end(); | |
} | |
} | |
lasso.items = function(_) { | |
if (!arguments.length) return items; | |
items = _; | |
items[0].forEach(function(d) { | |
var item = d3.select(d); | |
if(typeof item.datum() === 'undefined') { | |
item.datum({possible:false,selected:false}); | |
} | |
else { | |
//item.attr("d",function(e) {e.possible = false; e.selected = false; return e;}); | |
var e = item.datum(); | |
e.possible = false; | |
e.selected = false; | |
item.datum(e); | |
} | |
}) | |
return lasso; | |
}; | |
lasso.closePathDistance = function(_) { | |
if (!arguments.length) return closePathDistance; | |
closePathDistance = _; | |
return lasso; | |
}; | |
lasso.closePathSelect = function(_) { | |
if (!arguments.length) return closePathSelect; | |
closePathSelect = _==true ? true : false; | |
return lasso; | |
}; | |
lasso.isPathClosed = function(_) { | |
if (!arguments.length) return isPathClosed; | |
isPathClosed = _==true ? true : false; | |
return lasso; | |
}; | |
lasso.hoverSelect = function(_) { | |
if (!arguments.length) return hoverSelect; | |
hoverSelect = _==true ? true : false; | |
return lasso; | |
}; | |
lasso.on = function(type,_) { | |
if(!arguments.length) return on; | |
if(arguments.length===1) return on[type]; | |
var types = ["start","draw","end"]; | |
if(types.indexOf(type)>-1) { | |
on[type] = _; | |
}; | |
return lasso; | |
} | |
lasso.area = function(_) { | |
if(!arguments.length) return area; | |
area=_; | |
return lasso; | |
} | |
function sign(x) { | |
return x?x<0?-1:1:0; | |
} | |
return lasso; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment