|
//Width and height |
|
var margin = {top: 20, bottom: 50, right: 150, left: 150}; |
|
var w = 960 - margin.right - margin.left; |
|
var h = 350 - margin.top - margin.bottom; |
|
|
|
var dataset = []; |
|
// Create 20 random numbers from 1 to 30 |
|
for (var i = 0; i < 20; i++) { |
|
var randomNumber = Math.floor(Math.random()*30); |
|
dataset.push(randomNumber); |
|
} |
|
// Scales |
|
var xScale = d3.scale.ordinal() |
|
.domain(d3.range(dataset.length)) |
|
.rangeBands([0, w], 0.05); |
|
|
|
var yScale = d3.scale.linear() |
|
.domain([0, d3.max(dataset)]) |
|
.range([h, 0]); |
|
|
|
// Axes |
|
var xAxis = d3.svg.axis() |
|
.scale(xScale) |
|
.orient("bottom"); |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(yScale) |
|
.orient("left") |
|
.ticks(5); |
|
|
|
// Create SVG element |
|
var svg = d3.select("body") |
|
.append("svg") |
|
.attr("width", w + margin.left + margin.right) |
|
.attr("height", h + margin.top + margin.bottom); |
|
|
|
|
|
//////////////// |
|
// INITIAL ENTER |
|
|
|
// Creates rects |
|
svg.selectAll("rect") |
|
.data(dataset) |
|
.enter().append("rect") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
// Adjust x position acording to scale |
|
.attr("x", function(d, i) { |
|
return xScale(i); |
|
}) |
|
// Adjust y position acording to scale |
|
.attr("y", function(d) { |
|
return yScale(d); |
|
}) |
|
// Width and height acordding to scales |
|
.attr("width", xScale.rangeBand()) // need to understand rangeBand() better |
|
.attr("height", function(d) { |
|
return h - yScale(d); |
|
}) |
|
// Bars colors proportional to to value |
|
.attr("fill", function(d) { |
|
return "rgb(0, 0, " + (255 - d*8) + ")"; |
|
}); |
|
|
|
// Text that will be labels |
|
svg.selectAll("text") |
|
.data(dataset) |
|
.enter().append("text") |
|
.attr("class", "lbl") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
.text(function(d) { |
|
return d; |
|
}) |
|
.attr("text-anchor", "middle") |
|
.attr("x", function(d, i) { |
|
return xScale(i) + xScale.rangeBand() / 2; |
|
}) |
|
.attr("y", function(d) { |
|
if (d == 1) { |
|
return yScale(d) + 9; |
|
} |
|
if (d == 0) { |
|
return null; |
|
} |
|
return yScale(d) + 14; |
|
}) |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", function(d) { return 0.02*w + "px" }) |
|
.attr("font-weight", "bold") |
|
.attr("fill", "white"); |
|
|
|
// Axes |
|
svg.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(" + margin.left + "," + (h + margin.top) + ")") |
|
.call(xAxis); |
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
.call(yAxis); |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// GENERATE RANDOM ARRAY |
|
// |
|
// UPDATE |
|
d3.select(".generateRandom") |
|
.on("click", function() { |
|
// Do something mundane and annoying on click |
|
for (var i = 0; i < dataset.length; i++) { |
|
var randomNumber = Math.floor(Math.random()*50); |
|
dataset[i] = randomNumber; |
|
} |
|
|
|
// Update scales domain |
|
xScale.domain(d3.range(dataset.length)) |
|
yScale.domain([0, d3.max(dataset)]) |
|
|
|
/////////// BARS /////////// |
|
// |
|
// Update all rects |
|
svg.selectAll("rect") |
|
.data(dataset) |
|
.transition().duration(500).ease("linear") |
|
.attr("y", function(d) { |
|
return yScale(d); |
|
}) |
|
.attr("height", function(d) { |
|
return h - yScale(d); |
|
}) |
|
.attr("fill", function(d) { |
|
return "rgb(0, 0, " + (255 - d*8) + ")"; |
|
}); |
|
|
|
/////////// LABELS /////////// |
|
// |
|
// Update text |
|
svg.selectAll("text.lbl") |
|
.data(dataset) |
|
.transition().duration(500).ease("linear") |
|
.text(function(d) { |
|
return d; |
|
}) |
|
.attr("x", function(d, i) { |
|
return xScale(i) + xScale.rangeBand() / 2; |
|
}) |
|
.attr("y", function(d) { |
|
if (d == 1) { |
|
return yScale(d) + 9; |
|
} |
|
if (d == 0) { |
|
return null; |
|
} |
|
return yScale(d) + 14; |
|
}); |
|
|
|
/////////// AXES /////////// |
|
// |
|
// Update yAxis |
|
svg.selectAll("g.y.axis").call(yAxis); |
|
|
|
}); |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////// |
|
// ADD A NEW RANDOM NUMBER |
|
d3.select(".addRandom") |
|
.on("click", function() { |
|
// Push a new number |
|
dataset.push(Math.floor(Math.random()*50)); |
|
|
|
// Update scales domain |
|
xScale.domain(d3.range(dataset.length)) |
|
yScale.domain([0, d3.max(dataset)]) |
|
|
|
/////////// BARS /////////// |
|
// |
|
// Select |
|
var bars = svg.selectAll("rect").data(dataset) |
|
// Enter |
|
bars.enter().append("rect").attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
// Update |
|
bars.transition().duration(500) |
|
// Ajusta as posicoes para caber na tela de acordo com a escala |
|
.attr("x", function(d, i) { |
|
return xScale(i); |
|
}) |
|
// Ajusta a posicao vertical |
|
.attr("y", function(d) { |
|
return yScale(d); |
|
}) |
|
// Largura e altura proporcionais ao dataset |
|
.attr("width", xScale.rangeBand()) |
|
.attr("height", function(d) { |
|
return h - yScale(d); |
|
}) |
|
// Cores de acordo c o dataset |
|
.attr("fill", function(d) { |
|
return "rgb(0, 0, " + (255 - d*8) + ")"; |
|
}); |
|
|
|
/////////// LABELS /////////// |
|
// |
|
// Select |
|
var labels = svg.selectAll("text.lbl").data(dataset) |
|
// Enter |
|
labels.enter().append("text") |
|
.attr("class", "lbl") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
//Update |
|
labels.transition().duration(500) |
|
.text(function(d) { |
|
return d; |
|
}) |
|
.attr("text-anchor", "middle") |
|
.attr("x", function(d, i) { |
|
return xScale(i) + xScale.rangeBand() / 2; |
|
}) |
|
.attr("y", function(d) { |
|
if (d == 1) { |
|
return yScale(d) + 9; |
|
} |
|
if (d == 0) { |
|
return null; |
|
} |
|
return yScale(d) + 14; |
|
}) |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", function(d) { return 0.02*w + "px" }) |
|
.attr("font-weight", "bold") |
|
.attr("fill", "white"); |
|
|
|
/////////// AXES /////////// |
|
// |
|
// Update |
|
svg.selectAll("g.y.axis").call(yAxis); |
|
|
|
if (dataset.length <= 30) { |
|
xAxis.tickValues(xScale.domain().filter(function(d, i) { return !(i % 1); })) // change the ticks back to normal |
|
svg.selectAll("g.x.axis").call(xAxis); |
|
} else { |
|
xAxis.tickValues(xScale.domain().filter(function(d, i) { return !(i % 2); })) // change the ticks if x is large |
|
svg.selectAll("g.x.axis").call(xAxis); |
|
} |
|
|
|
}); |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
// REMOVES THE LAST RANDOM NUMBER |
|
d3.select(".removeRandom") |
|
.on("click", function() { |
|
// Remove one value from array |
|
dataset.pop(); |
|
|
|
// Update scales domain |
|
xScale.domain(d3.range(dataset.length)) |
|
yScale.domain([0, d3.max(dataset)]) |
|
|
|
/////////// BARS /////////// |
|
// |
|
// Select |
|
var bars = svg.selectAll("rect").data(dataset); |
|
// Update |
|
bars.transition().duration(500) |
|
.attr("x", function(d, i) { |
|
return xScale(i); |
|
}) |
|
// Ajusta a posicao vertical |
|
.attr("y", function(d) { |
|
return yScale(d); |
|
}) |
|
// Largura e altura proporcionais ao dataset |
|
.attr("width", xScale.rangeBand()) |
|
.attr("height", function(d) { |
|
return h - yScale(d); |
|
}) |
|
// Cores de acordo c o dataset |
|
.attr("fill", function(d) { |
|
return "rgb(0, 0, " + (255 - d*8) + ")"; |
|
}); |
|
// Exit |
|
bars.exit() //References the exit selection (a subset of the update selection) |
|
.transition() //Initiates a transition on the one element we're deleting |
|
.duration(500) |
|
.attr("x", w) //Move past the right edge of the SVG |
|
.remove(); //Deletes this element from the DOM once transition is complete |
|
|
|
|
|
/////////// LABELS /////////// |
|
// |
|
// Select |
|
var labels = d3.selectAll("text.lbl").data(dataset); |
|
// Update |
|
labels.transition().duration(500) |
|
.text(function(d) { |
|
return d; |
|
}) |
|
.attr("x", function(d, i) { |
|
return xScale(i) + xScale.rangeBand() / 2; |
|
}) |
|
.attr("y", function(d) { |
|
if (d == 1) { |
|
return yScale(d) + 9; |
|
} |
|
if (d == 0) { |
|
return null; |
|
} |
|
return yScale(d) + 14; |
|
}); |
|
// Exit |
|
labels.exit().remove(); |
|
|
|
/////////// AXES /////////// |
|
// |
|
// Update |
|
svg.selectAll("g.y.axis").call(yAxis); |
|
|
|
if (dataset.length <= 30) { |
|
xAxis.tickValues(xScale.domain().filter(function(d, i) { return !(i % 1); })) // change the ticks back to normal |
|
svg.selectAll("g.x.axis").call(xAxis); |
|
} else { |
|
xAxis.tickValues(xScale.domain().filter(function(d, i) { return !(i % 2); })) // change the ticks if x is large |
|
svg.selectAll("g.x.axis").call(xAxis); |
|
} |
|
|
|
}); |