A simple stacked coloumn graph built using d3's stack layout.
The SVG tooltip is based on this gist by Mike Bostock. In short, the tooltip's group, comprised of a rect and a text element, are created when the chart is first drawn and set to be hidden. Action is applied to the stacks' rects: on mouseover the group become visible; on mousemove the mouse's XY position is captured and used to transform/translate the group.
If you ajust the tooltip's XY offset, keep in mind that there can be no overlap between the group and the mouse's position or the group's visibility will remain hidden.
forked from mstanaland's block: Stacked bar chart with tooltips
forked from anonymous's block: stacked-bars
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>d3.js learning</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
shape-rendering: crispEdges;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
}
path.domain {
stroke: none;
}
.y .tick line {
stroke: #ddd;
}
</style>
</head>
<body>
<script type="text/javascript">
// Setup svg using Bostock's margin convention
var margin = {top: 20, right: 160, bottom: 35, left: 30};
var width = 960 - margin.left - margin.right,
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 + ")");
/* Data in strings like it would be if imported from a csv */
var tf_data = [
{
name: "Justin Palmer",
colorIndex: "#6E7194",
data: [6, 37, 6, 12, 4, 7],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
{
name: "Dima Lashkov",
colorIndex: "#D3EE70",
data: [2, 2, 3, 18, 1, 4],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
{
name: "Doreen Ghafari",
colorIndex: "#C68C81",
data: [12, 2, 3, 2, 2, 8],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
{
name: "Vinky Ip",
colorIndex: "#734357",
data: [0, 2, 5, 2, 2, 8],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
{
name: "Achal Srinivasan",
colorIndex: "#3FA4B0",
data: [0, 2, 5, 2, 2, 8],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
{
name: "George Carollo",
colorIndex: "#5FD19A",
data: [0, 2, 5, 2, 2, 8],
dates: ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
},
]
var tf_dates = ["11/06/2017", "11/13/2017", "11/20/2017", "11/27/2017", "12/4/2017", "12/11/2017"]
// get list of users
tf_users = []
tf_data.map(function(d) {
tf_users.push(d.name);
});
var parse = d3.time.format("%Y").parse;
var new_parse = d3.time.format("%m/%d/%Y").parse;
var new_dataset = d3.layout.stack()(tf_users.map(function(user) {
i = -1
return tf_data.map(function(d) {
i += 1
return {x: new_parse(d.dates[i]), y: +d.data[i]};
});
}));
console.log(new_dataset)
// access, for each user, date array
function loop(dates, users, json) {
for (i = 0; i < dates.length; i++) {
for (j = 0; j < users.length; j++) {
console.log({x: new_parse(tf_dates[j]), y: +json[j].data[i]})
}
}
}
loop(tf_dates, tf_users, tf_data)
// Set x, y and colors
var x = d3.scale.ordinal()
.domain(new_dataset[0].map(function(d) { return d.x; }))
.rangeRoundBands([10, width-10], 0.02);
var y = d3.scale.linear()
.domain([0, d3.max(new_dataset, function(d) { return d3.max(d, function(d) { return d.y0 + d.y; }); })])
.range([height, 0]);
// get colors from data
var tf_colors = []
tf_data.map(function(d) {
tf_colors.push(d.colorIndex)
})
// Define and draw axes
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width, 0, 0)
.tickFormat( function(d) { return d } );
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format("%m/%d"));
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Create groups for each series, rects for each segment
var new_groups = svg.selectAll("g.conversions")
.data(new_dataset)
.enter().append("g")
.attr("class", "conversions")
.style("fill", function(d, i) { return tf_colors[i]; });
var rect = new_groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.attr("width", x.rangeBand())
.on("mouseover", function() { tooltip.style("display", null); })
.on("mouseout", function() { tooltip.style("display", "none"); })
.on("mousemove", function(d) {
var xPosition = d3.mouse(this)[0] - 15;
var yPosition = d3.mouse(this)[1] - 25;
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
tooltip.select("text").text(d.y);
});
// Draw legend
var legend = svg.selectAll(".legend")
.data(tf_colors)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(30," + i * 19 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {return tf_colors.slice()[i];});
legend.append("text")
.attr("x", width + 5)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d, i) {
switch (i) {
case 0: return "Justin Palmer";
case 1: return "Dima Lashkov";
case 2: return "Doreen Ghafari";
case 3: return "Vinky Ip";
case 4: return "Achal Srinivasan";
case 5: return "George Carollo"
}
});
// Prep the tooltip bits, initial display is hidden
var tooltip = svg.append("g")
.attr("class", "tooltip")
.style("display", "none");
tooltip.append("rect")
.attr("width", 30)
.attr("height", 20)
.attr("fill", "white")
.style("opacity", 0.5);
tooltip.append("text")
.attr("x", 15)
.attr("dy", "1.2em")
.style("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold");
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js