Trying to create line chart with Circle Tooltip - javascript

I am trying to create an interactive line chart with circle tooltip like the following https://bl.ocks.org/alandunning/cfb7dcd7951826b9eacd54f0647f48d3 .
My code is below:
HTML
<head>
<style>
circle {
fill: steelblue;
}
body {
font: 12px Arial;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
div.tooltip {
position: absolute;
text-align: center;
width: 80px;
height: 64px;
padding: 2px;
font: 14px sans-serif;
color: black;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.overlay {
fill: none;
pointer-events: all;
}
.focus circle {
fill: #F1F3F3;
stroke: #6F257F;
stroke-width: 5px;
}
.hover-line {
stroke: #6F257F;
stroke-width: 2px;
stroke-dasharray: 3, 3;
}
</style>
</head>
<body>
<svg class='line-chart2'></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="./regression.js"></script>
</body>
regression.js
var gdp = [387.65, 410.32, 415.73, 452.69, 462.14,
478.96, 508.06, 599.59, 699.68, 808.90,
920.31, 1201.11, 1186.95, 1323.94, 1656.61,
1823.04, 1827.63, 1856.72, 2039.12, 2102.39,
2274.22, 2600.81
]; //y or GDP of India
var years = ['1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017'];
var data_gdp = []
for (i = 0; i < years.length; i++) {
data_gdp.push({
year: years[i],
value: gdp[i]
})
}
function drawChart_gdp(data, class_name) {
var svgWidth = 1200,
svgHeight = 400;
var margin = {
top: 60,
right: 60,
bottom: 60,
left: 60
};
var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;
var svg = d3.select(class_name)
.attr("width", svgWidth)
.attr("height", svgHeight);
var bisectDate = d3.bisector(function(d) {
return d.year;
}).left;
var g = svg.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")"
);
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().rangeRound([height, 0]);
var line = d3.line()
.x(function(d) {
return x(new Date(parseInt(d.year), 0))
})
.y(function(d) {
return y(d.value)
})
x.domain(d3.extent(data, function(d) {
return new Date(parseInt(d.year), 0);
}));
y.domain(d3.extent(data, function(d) {
return d.value
}));
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.text("Year")
.attr("dy", "1.90em")
.attr("y", 5)
.attr("x", 500)
.attr("font-size", "20px")
.select(".domain")
.remove();
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", -80)
.attr("x", -55)
.attr("dy", "1.90em")
.attr("text-anchor", "center")
.attr("font-size", "20px")
.text("GDP ($)")
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
var focus = g.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("line")
.attr("class", "x-hover-line hover-line")
.attr("y1", 0)
.attr("y2", height);
focus.append("line")
.attr("class", "y-hover-line hover-line")
.attr("x1", width)
.attr("x2", width);
focus.append("circle")
.attr("r", 7.5);
focus.append("text")
.attr("x", 15)
.attr("dy", ".31em");
svg.append("rect")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() {
focus.style("display", null);
})
.on("mouseout", function() {
focus.style("display", "none");
})
.on("mousemove", function() { //problem in this function
var x0 = d3.timeFormat("%Y")(x.invert(d3.mouse(this)[0])),
i = bisectDate(data, x0, 1);
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.year > d1.year - x0 ? d1 : d0;
focus.attr("transform", "translate(" + x(d.year) + "," + y(d.value) + ")");
focus.select("text").text(function() {
return d.value;
});
focus.select(".x-hover-line").attr("y2", height - y(d.value));
focus.select(".y-hover-line").attr("x2", width + width);
});
}
drawChart_gdp(data_gdp, '.line-chart2');
I am suspecting that in the example the data is being pulled from json file but here is pulled from an array where the problem comes for and also I think the kind of data is little bit different too. My goals is just to create a circle tool which shows the value of y-axis.

The problem you're facing now is almost the opposite of the one you faced in your previous question: in that question, the problem was that you were dealing with date objects as if they were strings.
Now, you're dealing with strings as if they were date objects. In your data, the year is just a string, like "1996".
So, this:
focus.attr("transform", "translate(" + x(d.year) + "," + y(d.value) + ")");
Should be:
focus.attr("transform", "translate(" + x(d3.timeParse("%Y")(d.year)) + "," + y(d.value) + ")");
//parsing to a date here----------------------^
Here is the code with that change:
var gdp = [387.65, 410.32, 415.73, 452.69, 462.14,
478.96, 508.06, 599.59, 699.68, 808.90,
920.31, 1201.11, 1186.95, 1323.94, 1656.61,
1823.04, 1827.63, 1856.72, 2039.12, 2102.39,
2274.22, 2600.81
]; //y or GDP of India
var years = ['1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017'];
var data_gdp = []
for (i = 0; i < years.length; i++) {
data_gdp.push({
year: years[i],
value: gdp[i]
})
}
function drawChart_gdp(data, class_name) {
var svgWidth = 1200,
svgHeight = 400;
var margin = {
top: 60,
right: 60,
bottom: 60,
left: 60
};
var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;
var svg = d3.select(class_name)
.attr("width", svgWidth)
.attr("height", svgHeight);
var bisectDate = d3.bisector(function(d) {
return d.year;
}).left;
var g = svg.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")"
);
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().rangeRound([height, 0]);
var line = d3.line()
.x(function(d) {
return x(new Date(parseInt(d.year), 0))
})
.y(function(d) {
return y(d.value)
})
x.domain(d3.extent(data, function(d) {
return new Date(parseInt(d.year), 0);
}));
y.domain(d3.extent(data, function(d) {
return d.value
}));
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.text("Year")
.attr("dy", "1.90em")
.attr("y", 5)
.attr("x", 500)
.attr("font-size", "20px")
.select(".domain")
.remove();
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", -80)
.attr("x", -55)
.attr("dy", "1.90em")
.attr("text-anchor", "center")
.attr("font-size", "20px")
.text("GDP ($)")
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
var focus = g.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("line")
.attr("class", "x-hover-line hover-line")
.attr("y1", 0)
.attr("y2", height);
focus.append("line")
.attr("class", "y-hover-line hover-line")
.attr("x1", width)
.attr("x2", width);
focus.append("circle")
.attr("r", 7.5);
focus.append("text")
.attr("x", 15)
.attr("dy", ".31em");
svg.append("rect")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() {
focus.style("display", null);
})
.on("mouseout", function() {
focus.style("display", "none");
})
.on("mousemove", function() { //problem in this function
var x0 = d3.timeFormat("%Y")(x.invert(d3.mouse(this)[0])),
i = bisectDate(data, x0, 1);
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.year > d1.year - x0 ? d1 : d0;
focus.attr("transform", "translate(" + x(d3.timeParse("%Y")(d.year)) + "," + y(d.value) + ")");
focus.select("text").text(function() {
return d.value;
});
focus.select(".x-hover-line").attr("y2", height - y(d.value));
focus.select(".y-hover-line").attr("x2", width + width);
});
}
drawChart_gdp(data_gdp, '.line-chart2');
<head>
<style>
circle {
fill: steelblue;
}
body {
font: 12px Arial;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
div.tooltip {
position: absolute;
text-align: center;
width: 80px;
height: 64px;
padding: 2px;
font: 14px sans-serif;
color: black;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.overlay {
fill: none;
pointer-events: all;
}
.focus circle {
fill: #F1F3F3;
stroke: #6F257F;
stroke-width: 5px;
}
.hover-line {
stroke: #6F257F;
stroke-width: 2px;
stroke-dasharray: 3, 3;
}
</style>
</head>
<body>
<svg class='line-chart2'></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
</body>
As you know by now, all this confusion comes to the fact that you have strings in your data array, but x is a time scale. My advice: parse the strings in your data array, creating date objects, and be consistent in your code, dealing all data as date objects, not strings.

Related

Integrating d3.js Trend Chart (Area + Line) as data studio community visualisation

I am a data scientist. Mostly use python and SQL for code. I am using data studio for visualizations.So I am unfamiliar to JS. I know-how data studio community visualizations works. I want to make this chart(without markers). I follow this. I tried but didn't get success. Can anybody with me on this? or refer me d3.js data studio integration resources.
I really not sure what you want but for the chart without markers here what I think you want:
function addAxesAndLegend(svg, xAxis, yAxis, margin, chartWidth, chartHeight) {
var legendWidth = 200,
legendHeight = 100;
// clipping to make sure nothing appears behind legend
svg
.append("clipPath")
.attr("id", "axes-clip")
.append("polygon")
.attr(
"points",
-margin.left +
"," +
-margin.top +
" " +
(chartWidth - legendWidth - 1) +
"," +
-margin.top +
" " +
(chartWidth - legendWidth - 1) +
"," +
legendHeight +
" " +
(chartWidth + margin.right) +
"," +
legendHeight +
" " +
(chartWidth + margin.right) +
"," +
(chartHeight + margin.bottom) +
" " +
-margin.left +
"," +
(chartHeight + margin.bottom)
);
var axes = svg.append("g").attr("clip-path", "url(#axes-clip)");
axes
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + chartHeight + ")")
.call(xAxis);
axes
.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Time (s)");
var legend = svg
.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + (chartWidth - legendWidth) + ", 0)");
legend
.append("rect")
.attr("class", "legend-bg")
.attr("width", legendWidth)
.attr("height", legendHeight);
legend
.append("rect")
.attr("class", "outer")
.attr("width", 75)
.attr("height", 20)
.attr("x", 10)
.attr("y", 10);
legend
.append("text")
.attr("x", 115)
.attr("y", 25)
.text("5% - 95%");
legend
.append("rect")
.attr("class", "inner")
.attr("width", 75)
.attr("height", 20)
.attr("x", 10)
.attr("y", 40);
legend
.append("text")
.attr("x", 115)
.attr("y", 55)
.text("25% - 75%");
legend
.append("path")
.attr("class", "median-line")
.attr("d", "M10,80L85,80");
legend
.append("text")
.attr("x", 115)
.attr("y", 85)
.text("Median");
}
function drawPaths(svg, data, x, y) {
var upperOuterArea = d3.svg
.area()
.interpolate("basis")
.x(function(d) {
return x(d.date) || 1;
})
.y0(function(d) {
return y(d.pct95);
})
.y1(function(d) {
return y(d.pct75);
});
var upperInnerArea = d3.svg
.area()
.interpolate("basis")
.x(function(d) {
return x(d.date) || 1;
})
.y0(function(d) {
return y(d.pct75);
})
.y1(function(d) {
return y(d.pct50);
});
var medianLine = d3.svg
.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.pct50);
});
var lowerInnerArea = d3.svg
.area()
.interpolate("basis")
.x(function(d) {
return x(d.date) || 1;
})
.y0(function(d) {
return y(d.pct50);
})
.y1(function(d) {
return y(d.pct25);
});
var lowerOuterArea = d3.svg
.area()
.interpolate("basis")
.x(function(d) {
return x(d.date) || 1;
})
.y0(function(d) {
return y(d.pct25);
})
.y1(function(d) {
return y(d.pct05);
});
svg.datum(data);
svg
.append("path")
.attr("class", "area upper outer")
.attr("d", upperOuterArea)
.attr("clip-path", "url(#rect-clip)");
svg
.append("path")
.attr("class", "area lower outer")
.attr("d", lowerOuterArea)
.attr("clip-path", "url(#rect-clip)");
svg
.append("path")
.attr("class", "area upper inner")
.attr("d", upperInnerArea)
.attr("clip-path", "url(#rect-clip)");
svg
.append("path")
.attr("class", "area lower inner")
.attr("d", lowerInnerArea)
.attr("clip-path", "url(#rect-clip)");
svg
.append("path")
.attr("class", "median-line")
.attr("d", medianLine)
.attr("clip-path", "url(#rect-clip)");
}
function startTransitions(svg, chartWidth, chartHeight, rectClip, x) {
rectClip
.transition()
.duration(4000)
.attr("width", chartWidth);
}
function makeChart(data) {
var svgWidth = 960,
svgHeight = 500,
margin = { top: 20, right: 20, bottom: 40, left: 40 },
chartWidth = svgWidth - margin.left - margin.right,
chartHeight = svgHeight - margin.top - margin.bottom;
var x = d3.time
.scale()
.range([0, chartWidth])
.domain(
d3.extent(data, function(d) {
return d.date;
})
),
y = d3.scale
.linear()
.range([chartHeight, 0])
.domain([
0,
d3.max(data, function(d) {
return d.pct95;
})
]);
var xAxis = d3.svg
.axis()
.scale(x)
.orient("bottom")
.innerTickSize(-chartHeight)
.outerTickSize(0)
.tickPadding(10),
yAxis = d3.svg
.axis()
.scale(y)
.orient("left")
.innerTickSize(-chartWidth)
.outerTickSize(0)
.tickPadding(10);
var svg = d3
.select("body")
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// clipping to start chart hidden and slide it in later
var rectClip = svg
.append("clipPath")
.attr("id", "rect-clip")
.append("rect")
.attr("width", 0)
.attr("height", chartHeight);
addAxesAndLegend(svg, xAxis, yAxis, margin, chartWidth, chartHeight);
drawPaths(svg, data, x, y);
startTransitions(svg, chartWidth, chartHeight, rectClip, x);
}
var parseDate = d3.time.format("%Y-%m-%d").parse;
d3.json(
"https://gist.githubusercontent.com/rkirsling/33a9e350516da54a5d4f/raw/100dde6bc011fa2604f2c0fb2c160501e220a201/data.json",
function(error, rawData) {
if (error) {
console.error(error);
return;
}
var data = rawData.map(function(d) {
return {
date: parseDate(d.date),
pct05: d.pct05 / 1000,
pct25: d.pct25 / 1000,
pct50: d.pct50 / 1000,
pct75: d.pct75 / 1000,
pct95: d.pct95 / 1000
};
});
makeChart(data);
}
);
#import url(//fonts.googleapis.com/css?family=Open+Sans:400, 700);
svg {
font: 14px "Open Sans";
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
fill: #000;
}
.axis .tick line {
stroke: rgba(0, 0, 0, 0.1);
}
.area {
stroke-width: 1;
}
.area.outer,
.legend .outer {
fill: rgba(230, 230, 255, 0.8);
stroke: rgba(216, 216, 255, 0.8);
}
.area.inner,
.legend .inner {
fill: rgba(127, 127, 255, 0.8);
stroke: rgba(96, 96, 255, 0.8);
}
.median-line,
.legend .median-line {
fill: none;
stroke: #000;
stroke-width: 3;
}
.legend .legend-bg {
fill: rgba(0, 0, 0, 0.5);
stroke: rgba(0, 0, 0, 0.5);
}
.marker.client .marker-bg,
.marker.client path {
fill: rgba(255, 127, 0, 0.8);
stroke: rgba(255, 127, 0, 0.8);
stroke-width: 3;
}
.marker.server .marker-bg,
.marker.server path {
fill: rgba(0, 153, 51, 0.8);
stroke: rgba(0, 153, 51, 0.8);
stroke-width: 3;
}
.marker path {
fill: none;
}
.legend text,
.marker text {
fill: #fff;
font-weight: bold;
}
.marker text {
text-anchor: middle;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Trend Chart (Area + Line)</title>
</head>
<body>
</body>
<script src="http://d3js.org/d3.v3.js"></script>
</html>

Add tiptool to a brush function chart

Right now i have a brush function and two lines. I could add tiptool without brush function but since i have brush now, it wont focus anymore. And also i have two lines, so its hard to choose a appropriate tiptool. I wanted to add the tiptool only on the upper margin. I am new in javascript. Anyone could help me with it? Thank you so much
var margin = {
top: 10,
right: 10,
bottom: 100,
left: 40
},
margin2 = {
top: 430,
right: 10,
bottom: 20,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var color = d3.scale.category10();
var parseDate = d3.time.format("%m/%e/%Y %H:%M").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brush);
var line = d3.svg.line()
.defined(function(d) {
return !isNaN(d.power);
})
.interpolate("cubic")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.power);
});
var line2 = d3.svg.line()
.defined(function(d) {
return !isNaN(d.power);
})
.interpolate("cubic")
.x(function(d) {
return x2(d.date);
})
.y(function(d) {
return y2(d.power);
});
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("pvdata2.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "pvdate";
}));
data.forEach(function(d) {
d.date = parseDate(d.pvdate);
});
var sources = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
power: +d[name]
};
})
};
});
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([d3.min(sources, function(c) {
return d3.min(c.values, function(v) {
return v.power;
});
}),
d3.max(sources, function(c) {
return d3.max(c.values, function(v) {
return v.power;
});
})
]);
x2.domain(x.domain());
y2.domain(y.domain());
var focuslineGroups = focus.selectAll("g")
.data(sources)
.enter().append("g");
var focuslines = focuslineGroups.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
})
.attr("clip-path", "url(#clip)");
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
var contextlineGroups = context.selectAll("g")
.data(sources)
.enter().append("g");
var contextLines = contextlineGroups.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line2(d.values);
})
.style("stroke", function(d) {
return color(d.name);
})
.attr("clip-path", "url(#clip)");
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
svg.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 45)
.attr("dy", "0.71em")
.style("text-anchor", "end")
.text("Power (kW)");
});
function brush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.selectAll("path.line").attr("d", function(d) {
return line(d.values)
});
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);
}
// Active point element
var activePoint = svg.append('circle')
.attr({
cx: 0,
cy: 0,
r: 5,
'pointer-events': 'none'
})
.style({
stroke: 'none',
fill: 'red',
'fill-opacity': 0
});
svg {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.y.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.line {
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

How to render d3 graph ticks above shaded region or graph itself?

I want ticks to come above shaded region in graph, i have tried transparency but it will not work.
Due to some constraint i cannot change the way i am coloring green region, but its like this-> Shade area below above line with green, then area below bottom line as white(same as chart background color)
Now due to this, ticks are hiding behind, is there a way i can place them above? or redraw new ticks in shaded region?
Click here for image of graph
renderGraph: function(){
// Data notice the structure
//************************************************************
var data = [
[{'x':1,'y':7},{'x':2,'y':7},{'x':3,'y':7},{'x':4,'y':7},{'x':4.5,'y':8.1},{'x':6.3,'y':8.1},{'x':6.8,'y':7},{'x':8,'y':7},{'x':9,'y':8},{'x':10,'y':8}],
[{'x':1,'y':9},{'x':2,'y':8},{'x':3,'y':11},{'x':4,'y':10},{'x':5,'y':10},{'x':6,'y':9},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':10}],
[{'x':1,'y':9.5},{'x':2,'y':9},{'x':3,'y':10.5},{'x':4,'y':9},{'x':5,'y':10},{'x':6,'y':9},{'x':7,'y':11},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}],
[{'x':1,'y':8},{'x':2,'y':8},{'x':3,'y':8},{'x':4,'y':8},{'x':5,'y':10},{'x':6,'y':10},{'x':7,'y':8},{'x':8,'y':8},{'x':9,'y':9},{'x':10,'y':9}],
[{'x':1,'y':10},{'x':2,'y':10},{'x':3,'y':10},{'x':4,'y':11},{'x':5,'y':11},{'x':6.5,'y':11},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}]
];
var dataAboveLine = [{'x':1,'y':10},{'x':2,'y':10},{'x':3,'y':10},{'x':4,'y':11},{'x':5,'y':11},{'x':6.5,'y':11},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}];
var dataBelowLine = [{'x':1,'y':7},{'x':2,'y':7},{'x':3,'y':7},{'x':4,'y':7},{'x':4.5,'y':8.1},{'x':6.3,'y':8.1},{'x':6.8,'y':7},{'x':8,'y':7},{'x':9,'y':8},{'x':10,'y':8}];
var colors = [
'steelblue',
'RGB(0,93,135)',
'RGB(226,0,26)',
'RGB(142,166,78)'
]
var lineType = [
'0 1', //5 0
'5 0',
'5 0',
'8 5'
]
//************************************************************
// Create Margins and Axis and hook our zoom function
//************************************************************
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 12])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 16])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
//.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.orient("left");
var area = d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(height)
.y1(function(d) { return y(d.y); });
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 3])
.on("zoom", zoomed);
var vertical = d3.select("#chartHolder")
.append("div")
.attr("clip-path", "url(#clip)")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "1px")
.style("height", "450px")
// .style("top", "39px")
.style("top", "46px")
.style("bottom", "1px")
.style("left", "8px")
.style("background", "#000");
var horizontal = d3.select("#chartHolder")
.append("div")
.attr("clip-path", "url(#clip)")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "881px")
.style("height", "1px")
.style("top", "47px")
.style("bottom", "1px")
.style("left", "57px")
.style("background", "#000");
//************************************************************
// Generate our SVG object
//************************************************************
var svg = d3.select("#chartHolder").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "svgClass")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// svg.append("g")
// .attr("class", "x axis")
// .append("text")
// .attr("class", "axis-label")
// .attr("y", 500)
// .attr("x", 400)
// .text('new');
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.text('Hours');
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("path")
.datum(dataAboveLine)
.attr("class", "areaAbove")
.attr("d", area)
.attr("clip-path", "url(#clip)");
svg.append("path")
.datum(dataBelowLine)
.attr("class", "areaBelow")
.attr("d", area)
.attr("clip-path", "url(#clip)");
//************************************************************
// Create D3 line object and draw data on our SVG object
//************************************************************
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('stroke', function(d,i){
return colors[i%colors.length];
})
.style("stroke-dasharray", function(d,i){
return lineType[i%lineType.length];
})
.attr("d", line)
.attr("stroke-width","3px");
// Define the div for the tooltip
var div = d3.select("#chartHolder").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//************************************************************
// Draw points on SVG object based on the data given
//************************************************************
var points = svg.selectAll('.dots')
.data(data)
.enter()
.append("g")
.attr("class", "dots")
.attr("clip-path", "url(#clip)");
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.on("click", function(d){click(d)})
.attr('class','dot')
.attr("r", 3.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr('fill-opacity', function(d,i){
if(d.index==0||d.index==4||d.index==3){
return '0';
}
})
.attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
)
.on("mouseover", function(d) {
div.transition()
// .duration(200)
.style("opacity", .9);
div .html("X:"+d.point.x + "<br/>" +"Y:"+ d.point.y)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
// .duration(500)
.style("opacity", 0);
});
function click(d){
alert(JSON.stringify(d.point));
}
//************************************************************
// Zoom specific updates
//************************************************************
function zoomed() {
svg.select(".areaAbove").call(area);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
svg.select('.areaAbove').attr('d', area);
svg.select('.areaBelow').attr('d', area);
points.selectAll('circle').attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
);
}
var txtCycle = d3.select("#chartHolder").append("p")
.append("text")
.attr("class", "yaxis-label")
.attr("y", 463)
.attr("x", 400)
.text('Number of cycles');
var slider = d3.select("#chartHolder").append("p").append("input")
.datum({})
.attr("type", "range")
.attr("class","slider")
.attr("value", zoom.scaleExtent()[0])
.attr("min", zoom.scaleExtent()[0])
.attr("max", zoom.scaleExtent()[1])
.attr("step", (zoom.scaleExtent()[1] - zoom.scaleExtent()[0]) / 100)
.on("input", slided);
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'height','22');
svgimg.setAttributeNS(null,'width','350');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', 'xaxis.PNG');
svgimg.setAttributeNS(null,'x','580');
svgimg.setAttributeNS(null,'y','450');
svgimg.setAttributeNS(null, 'visibility', 'visible');
$('svg').append(svgimg);
function slided(d){
zoom.scale(d3.select(this).property("value"))
.event(svg);
}
//for crosshairs
d3.select("#chartHolder")
.on("mousemove", function(){
coord = d3.mouse(this);
mousex = coord[0];
mousey=coord[1];
// vertical.style("left", mousex+ "px" );
// horizontal.style("top", mousey +"px")
if((mousex+6)>935){
mousex=929;
}
if((mousex+6)<59){
mousex=53;
}
if((mousey+6)>495){
mousey=489;
}
if((mousey+6)<44){
mousey=39;
}
vertical.style("left", mousex+6+ "px" );
horizontal.style("top", mousey+6 +"px");
})
.on("mouseover", function(){
coord = d3.mouse(this);
mousex = coord[0];
mousey=coord[1];
if((mousex+6)>930){
mousex=924;
}
if((mousex+6)<51){
mousex=45;
}
if((mousey+6)<39){
mousey=33;
}
if((mousey+6)>487){
mousey=481;
}
// vertical.style("left", mousex + "px");
// horizontal.style("top", mousey +"px")});
vertical.style("left", mousex +6+ "px");
horizontal.style("top", mousey +6+"px")});
// add cross hairs and floating value on axis
/*
var chart = d3.select("svg");
var focusText = chart.append("g")
.attr("class","focus")
.style("display", "none");
focusText.append("text").attr({"x": 9, "dy": "0.35em"});
var focus = chart.append("g")
.attr("class","focus")
.style("display", "none");
//focus.append("text").attr({"x": 9, "dy": "0.35em"});
// horizontal crosshair
focus.append("line")
.attr({
"x1": -width,
"y1": 0,
"x2": width,
"y2": 0
});
// vertical crosshair
focus.append("line")
.attr({
"x1": 0,
"y1": -height,
"x2": 0,
"y2": height
});
chart.append("rect")
.attr({"class": "overlay" , "width": width , "height": height})
.on({
"mouseover": function() { focus.style("display", null); focusText.style("display", null); },
"mouseout": function() { focus.style("display", "none"); focusText.style("display", "none"); },
"mousemove": mousemove
});
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectDate(sample2, x0, 1),
d0 = sample2[i-1],
d1 = sample2[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.attr("transform", "translate(" + (d3.mouse(this)[0]) + "," + yScale(d.close) + ")");
focusText.attr("transform", "translate(" + (width-margin.right) + "," + yScale(d.close) + ")");
focusText.select("text").text("$" + d.close);
} */
//
}
renderGraph();
.sapUiBody{
background-color: white;
background-image: none;
}
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
.axis path {
fill: none;
stroke: #bbb;
shape-rendering: crispEdges;
}
.axis text {
fill: #555;
}
.axis line {
stroke: #e7e7e7;
shape-rendering: crispEdges;
}
.axis .axis-label {
font-size: 14px;
}
.yaxis-label{
left: 448px;
position: absolute;
display: block;
}
.line {
fill: none;
stroke-width: 2.0px;
}
.dot {
/* consider the stroke-with the mouse detect radius? */
stroke: transparent;
stroke-width: 10px;
cursor: pointer;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.areaBelow {
fill: white;
stroke-width: 0;
}
.areaAbove {
fill: RGB(142,166,78);
stroke-width: 0;
opacity: 0.34;
}
.dot:hover {
stroke: rgba(68, 127, 255, 0.3);
}
.slider{
width: 300px;
}
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>

Using d3-tip and CSS hover effect with d3 stacked bar chart

I am trying to make a stacked bar chart for a simple dataset (Below you can find codes and the data).
For the bar my mouse hovers on, I try to use CSS hover effect to change the color of the bar (A rect svg element with a class of .bar), and use d3-tip to show a tooltip displaying the region name that bar belongs.
Problems I am having are:
1 - The CSS hover effect is not working at all. (Please find the style sheet below)
2 - the tooltip is showing, but only if I move my mouse cursor from under the bar to enter it. If I move my mouse cursor from left/right/top of the bar, the "mouseover" seems like not being detected. When it is not detected, however if you click on the bar, it will be detected and tooltip will show.
3 - The tooltip is supposed to show the data for "d.State" (which is the region's abbreviation text), but it gives me undefined. "d.State" is working fine with the bar chart itself though - the axis ticks are created using these data.
The stacked bar is made based on this one: https://bl.ocks.org/mbostock/3886208
The tooltip and hover effect is based on this one: http://bl.ocks.org/Caged/6476579
The index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
</head>
<body>
<script type="text/javascript" src="viz.js"></script>
</body>
</html>
The viz.js:
// begin of the js file
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 320 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#7b6888", "#a05d56", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//define tooltip
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, 0])
.html(function(d) {
return "<strong>Region:</strong> <span style='color:red'>" + d.State + "</span>";
});
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 + ")");
//call tooltip
svg.call(tip);
d3.csv("data.csv", function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("font-size", 7);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Number of Organizations");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",1)"; });
state.selectAll(".bar")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("class", "bar")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
// end of the js file
The style.css:
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar:hover {
fill: steelblue;
pointer-events: all;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
The data.csv:
State,Non Profit,For Profit,Developer Group,Other
EP,28,142,15,16
EC,81,292,39,22
LC,73,91,23,9
MN,3,5,2,1
NA,102,561,26,19
SA,11,49,9,4
SS,28,10,10,3
If there is any part not clear please let me know. I am new to d3 and stackoverflow. Thanks!
The CSS hover effect is not working at all.(not was missing I guess ?)
The problem was it was already filled using d3. To override it just add !important to on hover fill
fill: steelblue !important;
The tooltip is showing, but only if I move my mouse cursor from under the bar to enter it. If I move my mouse cursor from left/right/top of the bar.(I didn't face any issue with your code ?)
I am not sure what exactly is the problem but, my guess is that, onmouseover will work only when you hover on it. So if the mouse pointer is already on the graph before it was generated, it won't show the tooltip.
The tooltip is supposed to show the data for "d.State".
The problem here is the State data is not attached to the element i.e, d.ages doesn't contain state value. Just attach the state value while binding data.
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 320 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#7b6888", "#a05d56", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//define tooltip
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, 0])
.html(function(d) {
return "<strong>Region:</strong> <span style='color:red'>" + d.State + "</span>";
});
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 + ")");
//call tooltip
svg.call(tip);
d3.csv("data.csv", function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("font-size", 7);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Number of Organizations");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",1)"; });
state.selectAll(".bar")
.data(function(d) {
for(var l = 0 ; l < d.ages.length ; l++) {
d.ages[l].State = d.State;
}
return d.ages; })
.enter().append("rect")
.attr("class", "bar")
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar:hover {
fill: steelblue !important;
pointer-events: all;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
</head>
<body>
<script type="text/javascript" src="viz.js"></script>
</body>
</html>

Tooltip displaying undefined values

I am having some issues with tooltips for my bar graph. For each stopname column, there should be a corresponding value of boarding and alightings shown in the tooltip, however, I am getting undefined values like here
Here is my code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: orange;
}
.bar:hover {
fill: orangered ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var margin = {top: 40, right: 20, bottom: 300, left: 40},
width = 1250 - margin.left - margin.right,
height = 750 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["orange", "orangered"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Stop:</strong> <span style='color:red'>" + d.stopname + "</span>" + "<br><br><strong>Mean no. of boardings:</strong> <span style='color:red'>" + d.meanboardings + "</span>"+ "<br><br><strong>Mean no. of alightings:</strong> <span style='color:red'>" + d.meanalightings + "</span>";
})
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 + ")");
svg.call(tip);
d3.tsv("data.tsv", function(d){
return {
stopname: d.stopname,
meanboardings: +d.meanboardings,
meanalightings: +d.meanalightings
};
}, function(error, data) {
console.log(data);
var dataset = d3.keys(data[0]).filter(function(key) { return key !== "stopname"
});
data.forEach(function(d) {
d.passengers = dataset.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.stopname; }));
x1.domain(dataset).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.passengers, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.5em")
.attr("transform", function(d) {
return "rotate(-90)"
});
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Mean no. of boardings and alightings");
var stopname = svg.selectAll(".stopname")
.data(data)
.enter().append("g")
.attr("class", "stopname")
.attr("transform", function(d) { return "translate(" + x0(d.stopname) + ",0)"; });
stopname.selectAll("rect")
.data(function(d) { return d.passengers; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
var legend = svg.selectAll(".legend")
.data(dataset.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
});
function type(d) {
d.data = +d.data;
return d;
}
</script>
TSV file:
stopname maxboardings meanboardings minboardings varboardings maxalightings meanalightings minalightings varalightings maxload meanload minload varload noofbuses
The Boardwalk Terminal (3908) 7 2.571428571 0 6.952380952 0 0 0 0 7 2.571428571 0 6.952380952 7
Highview / Sugar Maple (3329) 2 0.333333333 0 0.666666667 1 0.166666667 0 0.166666667 6 3 0 6.4 6
Highview / Highview Pl (3330) 0 0 0 0 1 0.166666667 0 0.166666667 5 2.833333333 0 5.366666667 6
....
Any help is appreciated, thank you!
You are getting undefined because you are using an undefined value for generating tooltip text.
In your html function, the data-object associated d you get for every rectangle/bar is of following format:
{name: "meanlightings", value: <some_value>}
It does not contain the stopname property and will only contain value for one of the fields in the original dataset.
You will have to rewrite the html callback as
.html(function(d) {
return "<strong>" + d.name + " :</strong> <span style='color:red'>" + d.value + "</span>";
})
However, if you want to show more properties, you will have to change the data that you are binding to rectangles.

Categories