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.
xxxxxxxxxx
<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>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js