Skip to content

Instantly share code, notes, and snippets.

@jhellier
Created October 16, 2015 23:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhellier/f9632fad18f1e077d23e to your computer and use it in GitHub Desktop.
Save jhellier/f9632fad18f1e077d23e to your computer and use it in GitHub Desktop.
Pick Up Sticks Sort

Built with blockbuilder.org

Randomly generates a bunch of sticks then randomly drops each stick into a pile. There is always one red stick in the pile. Click the "Sort It" button and the sticks are pulled out and placed on the bottom of the frame and then sorted. At this point the red stick should be very clearly seen and comparable. Hitting the reset button will generate a new random pile.

This was based on a sketch I did and then asked could I implement it in D3. This is how a lot of the projects I am doing go. It is a fun way to see what you can do. Also like the tons of examples the D3 community is developing, it provides inspiration to do other things. Clearly this was influenced heavily by other community examples, everything from the co-occurence matrix to the visual sorting algorithms.

An ongoing question for the animation is can we create meaning in the animation itself. Ideas like drawing the user's attention to specific pieces or creating meaning by the change in proximity to passing or merging objects.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg { width: 100%; height: 100%; }
button { margin: 10px; }
</style>
</head>
<body>
<button id="sortIt">Sort It</button>
<button id="reset">Reset</button>
<script>
var margin = {top: 20, right: 10, bottom: 20, left: 10};
var width = 960 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
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 + ")");
var xSpacing = 10,
xMargin = 15,
animSpeed = 3000, //3 secs
chaosSVG;
function layoutLines() {
chaosSVG = svg
.append("svg")
.attr("width", width + margin.left + margin.right )
.attr("height", height + margin.top + margin.bottom)
.attr("id","chaosSVG");
var data = [],
numOfItems = 75,
vizMarginX = 200,
vizMarginY = 40,
randomTarget = Math.floor(Math.random() * numOfItems),
randomMultiple = 350; //The length of the lines can be from 0 - this number
//Generate the lines
for (var i = 0; i < numOfItems; i++) {
var setPoints = {};
setPoints.x1 = Math.floor(Math.random() * randomMultiple);
setPoints.y1 = Math.floor(Math.random() * randomMultiple);
setPoints.x2 = Math.floor(Math.random() * randomMultiple);
setPoints.y2 = Math.floor(Math.random() * randomMultiple);
data.push(setPoints);
}
chaosSVG.selectAll("line").remove();
chaosSVG.selectAll("line")
.data(data)
.enter()
.append("line")
.attr("x1", function(d) { return d.x1 + vizMarginX;})
.attr("y1", function(d) { return d.y1 + vizMarginY;})
.attr("x2", function(d) { return d.x2 + vizMarginX;})
.attr("y2", function(d) { return d.y2 + vizMarginY;})
.attr("stroke-width", function(d,i) {
if (i == randomTarget) {
return 3;
} else {
return 2;
}
})
.attr("stroke", function(d,i) {
if (i == randomTarget) {
return "red";
} else {
return "black";
}
})
chaosSVG
.append("text")
.attr("id","chaosText")
.attr("x", 80)
.attr("y", height + 30)
.style("font-weight","bold")
.style("font-style","sans-serif")
.style("font-size", 26)
.style("fill","blue")
.text("Needle in a Haystack");
d3.select("#sortIt")
.on("click", function() {
d3.select("body").selectAll("line")
.transition()
.duration(animSpeed)
.attr("x1", function(d,i) { return (i * xSpacing) + xMargin; })
.attr("y1", function(d) { return height;})
.attr("x2", function(d,i) { return (i * xSpacing) + xMargin;})
.attr("y2", function(d) {
console.log("What");
var factor = Math.floor(Math.sqrt(Math.pow(d.x2 - d.x1,2) + Math.pow(d.y2 - d.y1,2)));
d.lineLength = factor;
return height - factor; });
//Call after the initial animation is complete.
setTimeout(function() {
sortIt();
}, animSpeed);
});
d3.select("#reset")
.on("click", function() {
d3.select("#chaosSVG").remove();
layoutLines();
});
};
(function() {
layoutLines();
})();
//Sort the lines by length
function sortIt() {
chaosSVG
.select("#chaosText")
.transition()
.duration(1000)
.text("Find what you are looking for");
chaosSVG.selectAll("line")
.sort(function(a,b) {
return d3.ascending(a.lineLength,b.lineLength);
})
.transition()
.duration(2000)
.attr("x1", function(d,i) { return ((i + 2) * xSpacing) + xMargin;})
.attr("y1", function(d) { return height;})
.attr("x2", function(d,i) { return ((i + 2) * xSpacing) + xMargin})
.attr("y2", function(d) { return height - d.lineLength;});
};
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment