|
<!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> |