Skip to content

Instantly share code, notes, and snippets.

@jalapic
Last active September 20, 2015 23:25
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 jalapic/fc6b42a0860ee9a24c62 to your computer and use it in GitHub Desktop.
Save jalapic/fc6b42a0860ee9a24c62 to your computer and use it in GitHub Desktop.
bars: groups, events

Bars: groups, tooltips, events

Adapted from Scott Murray's examples. Used for my own learning:

  • use div for tooltip styling

  • use css class for event styling

  • mouseover / mouseout

  • use d3.event to determine mouse location

  • use groups to group individual bars and text elements and then position each with respect to each other

  • use .filter to change style of individual datapoints/elements

  • add class after filtering data and use css to style these data separately

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<title>D3: An HTML div as tooltip</title>
<style type="text/css">
body {
background-color: gray;
}
svg {
background-color: white;
}
g.bar text {
font-family: sans-serif;
font-size: 11px;
fill: white; /*use fill with svg, not color, to color*/
font-style: bold;
text-anchor: middle;
opacity: 0;
}
/* Commented out, now that we have a <div> tooltip */
/*
g.bar.highlight text {
opacity: 1;
}
*/
g.bar.highlight rect {
fill: #15ff00;
stroke: #2a7a00;
}
g.bar.highlight rect.filtereddata { /*rect.filtereddata refers to data selected based on value and class was only applied to rect element of the group */
fill: #fdcb4e;
stroke: #415b00;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
/* Styling for new <div> */
#tooltip {
position: absolute;
top: 0;
left: 0;
z-index: 10;
margin: 0;
padding: 10px;
width: 15px;
height: 12px;
color: white;
font-family: sans-serif;
font-size: 12px;
font-weight: bold;
text-align: center;
background-color: rgba(0, 0, 0, 0.75);
opacity: 0; /* initially not visible */
pointer-events: none;
}
</style>
</head>
<body>
<!-- New HTML div functions as our tooltip -->
<div id="tooltip">
</div>
<script type="text/javascript">
//Width, height, padding
var w = 800;
var h = 450;
var padding = 25;
//Array of dummy data values
var dataset = [ 1, 4, 8, 9, 11, 15, 22, 24, 22, 21,
17, 12, 15, 11, 12, 7, 6, 8, 3, 5 ];
//Configure x and y scale functions
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([ padding, w - padding ], 0.1); //gap bt bars
var yScale = d3.scale.linear()
.domain([ 0, d3.max(dataset) ])
.rangeRound([ h - padding, padding ]);
//Configure y axis generator
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(6)
;
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create groups
var groups = svg.selectAll("g")
.data(dataset) // bind data to the group
.enter()
.append("g")
.attr("class", "bar") // give each 'g' a bar class
//
//Instead of positioning each rect and text element
//individually, now we position the entire *group*.
//Then the rects and gs just need to be nudged a bit
//in the right direction.
//
//For simplicity, the transform here is only being used
//for the x direction. Note the y value for all groups
//is zero.
//
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
})
//
//Also, the mouseover/mouseout behavior is now on the
//group level, not on individual rects. This is so mousing
//over *anywhere* on the group (e.g., on the labels themselves)
//can trigger the highlight behavior.
//
.on("mouseover", function(d) {
d3.select(this)
.classed("highlight", true); //adding class dynamically makes it easier to adjust styles without many lines here
//Position the tooltip <div> and set its content
var x = d3.event.pageX;
var y = d3.event.pageY - 40;
d3.select("#tooltip")
.style("left", x + "px") //with tooltips define top left corner
.style("top", y + "px")
.style("opacity", 1)
.text(d);
//Note: No need for an anonymous function here,
//e.g. function(d) {…}, because the data value
//'d' we want here belongs to the <g> element
//on which mouseover was triggered, not the
//tooltip div (which has no data bound to it).
})
.on("mouseout", function() {
d3.select(this)
.classed("highlight", false); // no longer has class highlight
//Hide the tooltip - revert back to invisible
d3.select("#tooltip")
.style("opacity", 0);
});
//Add bar to each group
// initially starts at bottom of graph y=(h-padding), height=0
// also starts intitially at x=0- as defined above in transform,
// all bars start at their own 0.
// store initial info in rects so can then apply .transition() to rects
var rects = groups.append("rect")
.attr("x", 0)
.attr("y", function(d) {
return h - padding;
})
.attr("width", xScale.rangeBand())
.attr("height", 0)
.attr("fill", "#4400ff"); //initial color
//Add label to each group
groups.append("text")
.attr("x", xScale.rangeBand() / 2)
.attr("y", function(d) {
return yScale(d) + 14;
})
.text(function(d) {
return d;
})
//Transition rects into place
rects.transition()
.delay(function(d, i) { //kind of goes in order left to right
return i * 100;
})
.duration(1500)
.attr("y", function(d) {
return yScale(d);
})
.attr("height", function(d) {
return h - padding - yScale(d);
})
.filter(function(d) { //filter and if true do following
if (d > 20) {
return true;
}
return false;
})
.attr("fill", "#84eeff") //change fill if above is true- this is not a color that is designated by css - it is done by javascript
// add another class here by which can change hover only for high value highlighted?
.attr("class", "filtereddata") // adds class *only* to the rect part of filtered <g>
;
//Create y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)") //location y-axis
.attr("opacity", 0) //initially invisible
.call(yAxis)
.transition() //transitions in
.delay(2000)
.duration(1500)
.attr("opacity", 1.0);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment