D3.js div blocks mouseover event in svg - d3.js

If I create a simple scatter plot using d3.js, I can record the mouseover events on the circle elements by printing 'hey' to the console:
http://jsfiddle.net/pkerpedjiev/opmhaz0n/
<!DOCTYPE html>
<meta charset="utf-8">
<div class="chart" style="position: aboslute; left: 0px: top: 0px; width: 300px; height: 200px;" ></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var xVals = [4, 8, 15, 16, 23, 42,72];
var yVals = [13, 49, 34, 2, 22, 23, 44];
var data = xVals.map(function(d,i) { return [d, yVals[i]]; });
var width=300;
var height=200;
console.log('data:', data);
/*
var div = d3.select(".chart").append("div")
.style("position", "absolute")
.style("width", width + "px")
.style("height", height + "px")
.style("left", 0 + "px")
.style("top", 0 + "px")
.style("opacity", 0.2);
*/
var svg = d3.select(".chart")
.append("svg")
svg.selectAll('circle')
.data(data)
.enter()
.append("circle")
.attr('cx', function(d) { return d[0]; })
.attr('cy', function(d) { return d[1]; })
.attr('r', 4)
.attr('fill', 'black')
.on('mouseover', function(d) { console.log('hey'); });
</script>
If I add a div behind the svg, however, the mouseover event doesn't get recorded:
http://jsfiddle.net/pkerpedjiev/Lxgbycr8/1/
<!DOCTYPE html>
<meta charset="utf-8">
<div class="chart" style="position: aboslute; left: 0px: top: 0px; width: 300px; height: 200px;" ></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var xVals = [4, 8, 15, 16, 23, 42,72];
var yVals = [13, 49, 34, 2, 22, 23, 44];
var data = xVals.map(function(d,i) { return [d, yVals[i]]; });
var width=300;
var height=200;
console.log('data:', data);
var div = d3.select(".chart").append("div")
.style("position", "absolute")
.style("width", width + "px")
.style("height", height + "px")
.style("left", 0 + "px")
.style("top", 0 + "px")
.style("opacity", 0.2);
var svg = d3.select(".chart")
.append("svg")
svg.selectAll('circle')
.data(data)
.enter()
.append("circle")
.attr('cx', function(d) { return d[0]; })
.attr('cy', function(d) { return d[1]; })
.attr('r', 4)
.attr('fill', 'black')
.on('mouseover', function(d) { console.log('hey'); });
</script>
Is there a way to register the 'mouseover' event when there's a div in the background behind the svg?

The positioning of the elements is interfering with what you may expect for mouse events here, in particular you need to set position to absolute for the SVG as well to make it appear in front of the div.
If you want the SVG to "catch" events only on certain elements, set pointer-events to none on the SVG and to all on the elements you want to receive the events.

Related

Switch between datasets in a d3 barchart

I need to switch between two datasets from the same csv file,
I have a small dataset of predicted v actual league positions from last years English premier League.
dataset1 = Actual League Position
dataset2 = Predicted league Position
My render data function does not seem to be working as my second dataset (i.e. Predicted) is not displayed when i click the radio button - see attached pic - only the actual position dataset is being displayed
I've provided a link to my code: github link to my code
Copy of relevant code below
function render(data){
var bars = g.selectAll("bar")
.data(data)
//enter
bars.enter().append("rect")
.attr("class", "bar")
.attr("x1", 0)
.attr("x2", 0)
.attr("y", function(d) { return y(d.Team); })
.attr("height", y.bandwidth())
.attr("width", function(d) { return x2(d.Predicted_Finish); })
.style("fill", "#a02f2b")
//exit
bars.exit()
.transition()
.duration(300)
.remove()
}
function init()
{
//setup the svg
var svg = d3.select("svg"),
margin = {top: 20, right: 10, bottom: 65, left: 110}//position of axes
frame
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
//setup our ui
d3.select("#Actual")
.on("click", function(d,i) {
console.log(Actual);
render(Actual)
})
d3.select("#Predicted")
.on("click", function(d,i) {
console.log(Predicted);
render(Predicted)
})
render(Actual)
}
init();
This code can be significantly simplified.
First, couple of format problems:
Improperly placed <body>, and no </body> or </html>
<form> around your buttons is not needed (it's causing a submit)
Second, your code can be restructured. You don't need a full enter, update, exit pattern here since your data doesn't really change. You just want to toggle between two variables in your single dataset. With that in mind, here's how it ends up looking:
<head>
<meta charset="utf-8">
<title>CSS Example</title>
<link href="https://fonts.googleapis.com/css?family=Passion+One" rel="stylesheet">
<style>
.my-text {
font-size: 1.95em;
font-family: 'Passion One', cursive;
fill: #000000;
}
.bar {
fill: #71df3e;
}
.bar:hover {
fill: white;
}
.axis--x path {
display: none;
}
body {
background-color: orange;
}
.axisx text {
fill: black;
}
.axisy text {
fill: black;
}
.axisx line {
stroke: black;
}
.axisy line {
stroke: black;
}
.axisx path {
stroke: black;
}
.axisy path {
stroke: black;
}
</style>
</head>
<body>
<div id="buttons">
<button id="Actual">Actual</button>
<button id="Predicted">Predicted</button>
</div>
<svg width="1200" height="500">
<text class="my-text" x="330" y="20">EPL PREDICTIONS VERSUS REALITY</text>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
//define svg canvas
var svg = d3.select("svg"),
margin = {
top: 20,
right: 10,
bottom: 65,
left: 110
} //position of axes frame
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
//next our graph
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(d) {
d.Actual_Finish = +d.Actual_Finish;
d.Predicted_Finish = +d.Predicted_Finish;
return d;
}, function(error, data)
{
if (error) throw error;
data = data;
//define our x and y axis scales and variables, remembering we have 2 x variables
x1 = d3.scaleLinear().rangeRound([800, 1])
//experiment with the max numbers to bring the x scale within the margin
.domain([0, d3.max(data, function(d) {
return d.Actual_Finish;
})]);
y = d3.scaleBand().rangeRound([0, height])
.padding(0.5).domain(data.map(function(d) {
return d.Team;
}));
//append x axis to svg
g.append("g")
.style("font", "14px arial") //font and size of x axis labels
.attr("class", "axisx")
.call(d3.axisBottom(x1).ticks(20))
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x1))
.append("text")
.attr("x", 450) //position of x1 axis label: x co-ordinate
.attr("y", 35) //position of x axis label: y co-ordinate
.attr("dx", "1.0em") //also position of X axis label
.attr("text-anchor", "middle")
.text("League Position");
//append y axis to svg
g.append("g") //append y axis to svg
.style("font", "14px arial") //font and size of y axis labels
.attr("class", "axisy")
.call(d3.axisLeft(y).ticks(20)) //no. of ticks on y axis
.append("text")
.attr("transform", "rotate(-360)") //rotate the axis label text by -90
.attr("y", -20) //position of y axis label
.attr("dy", "1.0em") //sets the unit amount the y axis label moves above
.attr("text-anchor", "end")
.text("Team");
var bars = g.selectAll('.bar')
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x1", 0)
.attr("x2", 0)
.attr("height", y.bandwidth())
.style("fill", "#a02f2b");
render('Actual_Finish')
function render(which) {
bars.attr("y", function(d) {
return y(d.Team);
})
.attr("width", function(d) {
return x1(d[which]);
});
}
d3.select("#Actual")
.on("click", function(d, i) {
render('Actual_Finish')
});
d3.select("#Predicted")
.on("click", function(d, i) {
render('Predicted_Finish')
});
});
</script>
</body>
</html>
Running code can be seen here.

How can I add a background colour behind PNG, when image URL is pulled from my D3.js dataset?

I am making a scatterplot, and pulling in an image fill for each circle on the plot. The problem is that the images are PNG's with transparent backgrounds. This means my overlapping circles show through each other:
Seen here - http://i.stack.imgur.com/bphon.png
I have tried setting a background colour with the CSS, but it seems to be completely overwritten by the .style("fill") in the JS. And I am looking to pull in 30ish images, so I don't want to have to save them all to be able to load the images with my CSS.
So, my question is, is there a way to put a white background behind my PNGs, while pulling those PNGs from URL's contained in my dataset?
Thanks for the help
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis-text {
font-family: sans-serif;
font-size: 11px;
background-color: white;
font-weight: bold;
}
.teamcircle {
background-color: white;
}
</style>
</head>
<body>
<div>
<input type="button" id="playerbtn" value="See Player View">
<input type="button" id="teambtn" value="See Team View">
</div>
<div id="data">
<div id="player-circles">
</div>
</div>
<script type="text/javascript">
//Width and height
var margin = {top: 50, right: 20, bottom: 30, left: 40};
var w = 960 - margin.left - margin.right;
var h = 500 - margin.top - margin.bottom;
//Create scale functions
var xScale = d3.scale.linear()
.range([0, w]);
var yScale = d3.scale.linear()
.range([h, 0]);
// var color = d3.scale.color();
// Define the Axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Load the TEAM data set
var teamdata = d3.tsv("team.tsv", function(error, teamdata) {
if (error) throw error;
teamdata.forEach(function(d) {
d.entriesper60 = +d.entriesper60;
d.carryinpercent = +d.carryinpercent;
});
xScale.domain(d3.extent(teamdata, function(d) { return d.carryinpercent; })).nice();
yScale.domain(d3.extent(teamdata, function(d) { return d.entriesper60; })).nice();
//Create X axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.append("text")
.attr("class", "axis-text")
.attr("x", w)
.attr("y", -6)
.style("text-anchor", "end")
.text("Carry-in %");
//Create Y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "axis-text")
.attr("y", -20)
.attr("z", 0)
.style("text-anchor", "middle")
.text("Entries/60")
// DEFS & Pattern for images
svg.append("defs")
.selectAll("pattern")
.data(teamdata)
.enter()
.append("pattern")
.attr('id', function(d, i) {
return d.name;
})
// .attr('patternUnits', 'userSpaceOnUse')
.attr('width', 20)
.attr('height', 20)
.append("image")
.attr("xlink:href", function(d) {
return d.image + d.name;
})
.attr('width', 20)
.attr('height', 20)
.attr("transform", "translate(2, 2)");
// Create TEAM Circles
svg.selectAll("circle")
.data(teamdata)
.enter()
.append("circle")
.attr("class", "teamcircle")
.style("stroke", function(d) { return d.hex; })
.style("stroke-width", 2)
.style("stroke-opacity", .8)
.attr("r", 12)
.attr("cx", function(d) { return xScale(d.carryinpercent); })
.attr("cy", function(d) { return yScale(d.entriesper60); })
.attr("fill", function(d) { return "url(#" + d.name + ")";
});
});
</script>
</body>
</html>
The best way I can think of is to create a group for every circle, and create a circle with a white background first. Something like this:
var teamCircle = svg.selectAll("g.teamcircle")
.data(teamdata)
.enter()
.append("g")
.attr("class", "teamcircle")
.transform(function(d){return "translate(" + xScale(d.carryinpercent) + "," + yScale(d.entriesper60) + ")"});
teamCircle.append("circle")
.attr("fill", "white")
.attr("r", 12)
teamCircle.append("circle")
.style("stroke", function(d) { return d.hex; })
.style("stroke-width", 2)
.style("stroke-opacity", .8)
.attr("r", 12)
.attr("fill", function(d) { return "url(#" + d.name + ")";

D3: display graph in tooltip

I know it is possible to display an image in a D3 tooltip. What I am trying to do is to display a bar graph in a tooltip (i.e when the mouse hovers over the object a bar graph appears). I have adapted code from http://bl.ocks.org/jarobertson/1483052#gistfile1.html and combined it with the bar graph code by Robert Lewand. And well, it doesn't work. I dont even get any errors in the console that could perhaps put me on the right path. Is it possible to do? Here is my code:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.27.1"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
div.tooltip {
position: absolute;
text-align: center;
width: 500px;
height: 550px;
padding: 8px;
font: 10px sans-serif;
background: #ddd;
border: solid 1px #aaa;
border-radius: 8px;
pointer-events: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: middle;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 960,
h = 500;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
svg.append("svg:g")
.attr("transform", "translate(480,50)rotate(60)scale(2)")
.append("svg:rect")
.attr("width", 140)
.attr("height", 140)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover() {
div.transition()
.duration(500)
.style("opacity", 1);
}
// where the tooltip previosly contained an image
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
function mouseout() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
// make bar graph
var width = 300,
height = 300;
var y = d3.scale.linear()
.range([height, 0]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
d3.tsv("data.tsv", type, function(error, data) {
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var barWidth = width / data.length;
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; });
bar.append("rect")
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d.value) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>
</body>
</html>
Thanks in advance!
apologies, the data.tsv file contains the following:
Sentiment value
Strongly positive 211
Positive 222
Neutral 654
Negative 618
Strongly negative 343
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.27.1"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
div.tooltip {
position: absolute;
text-align: center;
width: 500px;
height: 550px;
padding: 8px;
font: 10px sans-serif;
background: #ddd;
border: solid 1px #aaa;
border-radius: 8px;
pointer-events: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: middle;
}
</style>
<script type="text/javascript">
var w = 960,
h = 500;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
svg.append("svg:g")
.attr("transform", "translate(480,50)rotate(60)scale(2)")
.append("svg:rect")
.attr("width", 140)
.attr("height", 140)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover() {
div.transition()
.duration(500)
.style("opacity", 1);
}
// where the tooltip previosly contained an image
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
function mouseout() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
// make bar graph
var width = 300,
height = 300;
var y = d3.scale.linear()
.range([height, 0]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
d3.tsv("data.tsv", type, function(error, data) {
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var barWidth = width / data.length;
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; });
bar.append("rect")
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d.value) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>
'data.tsv' file is not with us,
and we have written only
function mousemove() {
div
.html("<h1>Bar Graph</h1><br> <svg class='chart'></svg>")
.style("left", (d3.event.pageX - 34) + "px")
.style("top", (d3.event.pageY - 12) + "px");
}
above function will place 'Bar Graph' text and one svg element in tooltip.
Hope you will get it.
If not ask for more......

group bar, from 3rd onwards coming separately

Here is my code.
http://jsfiddle.net/x8rax/9/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript' src='http://d3js.org/d3.v3.min.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<style type='text/css'>
.chart rect {
fill:#98abc5 ;
}
.chart2 rect {
fill:#8a89a6 ;
}
.chart3 rect {
fill:#7b6888 ;
}
.chart4 rect {
fill:#6b486b ;
}
.chart5 rect {
fill:#a05d56 ;
}
.chart6 rect {
fill:#d0743c ;
}
.chart7 rect {
fill:#ff8c00 ;
}
.chart {
position: absolute;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
var data = [4, 8, 15, 78, 100, 90];
var width = 420,
barHeight = 80;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight +")"; });
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 70);
var data = [10, 30, 20, 1000, 9, 500];
var width = 420,
barHeight = 80;
var chart = d3.select(".chart2")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + (i * barHeight + barHeight - 70 ) +")"; });
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 70);
var data = [500, 100, 60, 20, 1000, 9];
var width = 420,
barHeight = 80;
var chart = d3.select(".chart3")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + (i * barHeight + barHeight - 60 ) +")"; });
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 70);
}//]]>
</script>
</head>
<body>
<svg class="chart"></svg>
<svg class = "chart2"></svg>
<svg class = "chart3"></svg>
<svg class = "chart4"></svg>
<svg class = "chart5"></svg>
<svg class = "chart6"></svg>
<svg class = "chart7"></svg>
</body>
</html>
As you can see, 3rd onwards it's coming separately. I want to create the group bar chart with 7 different bars. I am right now stuck in 3rd.
It is coming separately because the svg tags with classes chart2 onwards are not positioned absolutely.
It works if you add a css rule as follows:
.chart2, .chart3, .chart4, .chart5, .chart6, .chart7{
position: absolute;
}
Please note however, that your current approach is not generic and you end up needing to create specific svg tags and repeating the bar chart creation code.
Please refer the grouped bar example at: http://bl.ocks.org/mbostock/3887051

d3.js adding id's to the stacked bar chart

I have created a stacked bar chart which depicts scanned and unscanned items as bars and also added the tooltip to represent the values of each stack when mouse is moved over. However when i move on a stack i would like to show tooltip like "UnScanned - 57 items" and when i move the mouse over the lower bar it should display "Scanned - 50" . I just need to differentiate the bar whether it is scanned or unscanned along with the data values displayed.
My code goes like:
<!DOCTYPE html>
<html>
<head>
<title>Scanned vs Non Scanned Data</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="../../js/Core_functions.js"></script>
<script type="text/javascript" src="../../js/graphic_functions.js"></script>
<style type="text/css">
svg {
width: 960px;
height: 500px;
border: solid 1px #ccc;
font: 10px sans-serif;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="container">
<h1>Mockup of Component Scanned Mapping DV</h1>
</div>
<script type="text/javascript">
var w = 960,
h = 500,
p = [20, 50, 30, 20],
x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]]),
y = d3.scale.linear().range([0, h - p[0] - p[2]]),
z = d3.scale.ordinal().range(["#819FF7", "#CB491A"]),
parse = d3.time.format("%m/%Y").parse,
format = d3.time.format("%b-%y");
/*var yAxis = d3.svg.axis()
.scale(y)
.ticks(12)
.orient("left");*/
var svg = d3.select("#container").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
d3.csv("scandata.csv", function(scan) {
// Transpose the data into layers by cause.
var scantypes = d3.layout.stack()(["scanned", "unscanned"].map(function(scans) {
return scan.map(function(d) {
return {x: parse(d.date), y: +d[scans]};
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain(scantypes [0].map(function(d) { return d.x; }));
y.domain([0, d3.max(scantypes[scantypes .length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each column.
var cause = svg.selectAll("g.scan")
.data(scantypes)
.enter().append("svg:g")
.attr("class", "scan")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = cause.selectAll("rect")
.data(Object)
.enter().append("svg:rect")
.attr("x", function(d,i) {
if (i ==0)
{
return x(d.x)+ 10 ;
}
else
{
return x(d.x);
}} )
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand()/2)
.on("mouseover", function(d){
return tooltip.style("visibility", "visible")
.text((d.y))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 20) + "px"); ;})
.on("mousemove", function(d){
return tooltip.style("visibility", "visible")
.text((d.y))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 20) + "px"); ;})
.on("mouseout", function(d){return tooltip.style("visibility", "hidden");})
.on("click", function(d){console.log(d);});
var tooltip = d3.select("#container")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "visible")
.text("Scanned vs UnScanned")
.style("font", "Arial")
.style("font-size", "14px");
// Add a label per date.
var label = svg.selectAll("text")
.data(x.domain())
.enter().append("svg:text")
.attr("x", function(d) { return x(d) + x.rangeBand() / 3; })
.attr("y", 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(format);
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w - p[1] - p[3])
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", -15)
.style("font-family","Arial 12px")
.attr("dy", ".25em")
.text(d3.format(",d"));
});
</script>
</body>
</html> </script>
</body>
</html>
My csv data :
date,scanned,unscanned
01/2014,10,90
02/2014,55,40
03/2014,45,23
04/2014,65,35
05/2014,100,20
06/2014,50,30
07/2014,10,90
08/2014,22,48
09/2014,0,100
10/2014,3,97
11/2014,22,60
12/2014,57,37
You could make this part of the data that you make for the chart:
var scantypes = d3.layout.stack()(["scanned", "unscanned"].map(function(scans) {
return scan.map(function(d) {
return {x: parse(d.date), y: +d[scans], type: scans};
});
}));
// more code...
.on("mouseover", function(d){
return tooltip.text(d.type + " - " + d.y);
});

Resources