Adding Text to the End of My Bars - D3 - javascript

I am currently making a Bar Graph which shows data in the form of a horizontal bar which grows based on the data put into the code. What I am trying to do here is make text appear next to the bars when they appear and change as the data does. I have already made a listener which changes the data appearing I just do not know how to make the data appear and change.
<!DOCTYPE html>
<html>
<head>
<meta>
<meta name="description" content="Drawing Shapes w/ D3 - " />
<meta charset="utf-8">
<title>Resources per Project</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
h1 {
font-size: 35px;
color: darkgrey;
font-family: Helvetica;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: black;
}
h2 {
font-size: 20px;
color: black;
font-family: Helvetica;
text-decoration: underline;
margin-left: 350px;
margin-top: 0px;
}
</style>
</head>
<body>
<h1>Resources used per Project</h1>
<p>Choose Month:
<select id="label-option">
<option value="April">April</option>
<option value="May">May</option>
<option value="June">June</option>
<option value="July">July</option>
<option value="August">August</option>
<option value="September">September</option>
</select>
<script type="text/javascript">
var width = 800
var height = 500
var emptyVar = 0
var dataArrayProjects = ['2G', 'An', 'At', 'Au', 'AW', 'Ch', 'CI', 'CN']
var April = [0.35, 1.66, 3.04, 1.54, 3.45, 2.56, 2.29, 1.37]
var May = [0.36, 1.69, 3.08, 1.54, 3.62, 2.61, 2.22, 1.44]
var June = [0.34, 1.7, 3.08, 1.63, 3.66, 2.68, 2.24, 1.51]
var July = [0.3, 1.72, 3.17, 1.67, 3.56, 2.56, 2.17, 1.44]
var August = [0.28, 1.79, 3.18, 1.71, 3.62, 2.73, 2.26, 1.54]
var September = [1.23, 1.74, 3.12, 1.61, 3.66, 2.71, 2.2, 1.48]
d3.select("#label-option").on("change", change)
function change() {
var data = April;
if (this.selectedIndex == 1){
data = May;
} else if (this.selectedIndex == 2){
data = June;
} else if (this.selectedIndex == 3){
data = July;
} else if (this.selectedIndex == 4){
data = August;
} else if (this.selectedIndex == 5){
data = September;
}
canvas.selectAll("rect")
.data(data)
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return i * 55
})
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
})
}
var widthScale = d3.scale.linear()
.domain([0, 4])
.range([0, width - 60]);
var heightScale = d3.scale.ordinal()
.domain(dataArrayProjects)
.rangePoints([10, height - 85]);
var color = d3.scale.linear()
.domain([0, 4])
.range(["#000033", "#22cdff"])
var xAxis = d3.svg.axis()
.ticks("30")
.scale(widthScale);
var yAxis = d3.svg.axis()
.scale(heightScale)
.orient("left");
var canvas = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40, 0)");
var bars = canvas.selectAll("rect")
.data(April)
.enter()
.append("rect")
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return i * 55
})
canvas.append("g")
.attr("transform", "translate(0, 430)")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.call(xAxis);
canvas.append("g")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.style("fill", "black")
.attr("class", "y axis")
.call(yAxis);
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
})
var yAxisLine = canvas.append("line")
.attr("x1", -3)
.attr("y1", 0)
.attr("x2", -3)
.attr("y2", 436)
.attr("stroke-width", 6)
.attr("stroke", "black");
canvas.selectAll("text")
.data(April)
.enter()
.append("text")
.text(function(d) {
return April;
})
.attr("x", function(d, i) {
return i * (width / April.length);
})
.attr("y", function(d) {
return height - (April * 4);
});
</script>
<h2>Resources</h2>
</body>
</html>
As you can see the data is not easily readable and hard to understand without knowing the precise number within the data. How do I make numbers appear next to the bars which say the exact amount of data being displayed. Please do not link other bar graphs with their own tooltips as I am not very good with d3.js and do not understand other graphs as well.

You can achieve that by first creating labels like below:
var texts = canvas.selectAll(".label")//select all DOMs with class label.
.data(April)
.enter()
.append("text")
.attr("class", "label")
.attr("x", function(d) {
return widthScale(d) + 10;//x location of the label
})
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return (i * 55) + 25; //y location of the label
})
.text(function(d, i) {
return d;
})
Finally in the update section do the following to update the labels.
texts = canvas.selectAll(".label")
.data(data)
.attr("x", function(d) {
return widthScale(d) + 10;
})
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return (i * 55) + 25
})
.text(function(d, i) {
return d;
})
working code here

Related

Data driven(D3.js) vertical grouped bar chart with tooltip, clickable legends and brush facilities

I want to build a chart using D3.js using vertical bar chart on provided data and selected filters.
Vertical grouped bar chart
Legends
Tooltip
Brush and zoom
Drill down
I have already added the filter for legends and tooltip, but facing issues while adding bursh. As i am new to D3, not sure what is the right way to integrate brush.
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js'></script>
</head>
<style>
g.axis path, g.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
g.brush rect.extent {
fill-opacity: 0.2;
}
.resize path {
fill-opacity: 0.2;
}
.n {
opacity: .8;
font-size: 10px;
margin-left: 4px;
font-family: sans-serif;
color: white;
padding: 6px;
background-color: #3C3176;
}
</style>
<body>
<style>
.axis .domain {
display: none;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// The scale spacing the groups:
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1);
// The scale for spacing each group's bar:
var x1 = d3.scaleBand()
.padding(0.05);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
d3.csv("data.csv", function(d, i, columns) {
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
return d;
}, function(error, data) {
if (error) throw error;
var keys = data.columns.slice(1);
const tip = d3.tip().html(d=> d.value);
svg.call(tip);
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();
g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("class","bar")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x1.bandwidth())
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return z(d.key); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0));
g.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
.text("Population");
// Initialize brush component
d3.brushX()
.handleSize(10)
.extent([10, 0], [g.width, g.height]);
// Append brush component
svg.append("g")
.attr("class", "brush")
.call(d3.brush);
var legend = g.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(keys.slice().reverse())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 17)
.attr("width", 15)
.attr("height", 15)
.attr("fill", z)
.attr("stroke", z)
.attr("stroke-width",2)
.on("click",function(d) { update(d) });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) { return d; });
var filtered = [];
////
//// Update and transition on click:
////
function update(d) {
//
// Update the array to filter the chart by:
//
// add the clicked key if not included:
if (filtered.indexOf(d) == -1) {
filtered.push(d);
// if all bars are un-checked, reset:
if(filtered.length == keys.length) filtered = [];
}
// otherwise remove it:
else {
filtered.splice(filtered.indexOf(d), 1);
}
//
// Update the scales for each group(/states)'s items:
//
var newKeys = [];
keys.forEach(function(d) {
if (filtered.indexOf(d) == -1 ) {
newKeys.push(d);
}
})
x1.domain(newKeys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { if (filtered.indexOf(key) == -1) return d[key]; }); })]).nice();
// update the y axis:
svg.select(".y")
.transition()
.call(d3.axisLeft(y).ticks(null, "s"))
.duration(500);
//
// Filter out the bands that need to be hidden:
//
var bars = svg.selectAll(".bar").selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
bars.filter(function(d) {
return filtered.indexOf(d.key) > -1;
})
.transition()
.attr("x", function(d) {
return (+d3.select(this).attr("x")) + (+d3.select(this).attr("width"))/2;
})
.attr("height",0)
.attr("width",0)
.attr("y", function(d) { return height; })
.duration(500);
//
// Adjust the remaining bars:
//
bars.filter(function(d) {
return filtered.indexOf(d.key) == -1;
})
.transition()
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x1.bandwidth())
.attr("fill", function(d) { return z(d.key); })
.duration(500);
// update legend:
legend.selectAll("rect")
.transition()
.attr("fill",function(d) {
if (filtered.length) {
if (filtered.indexOf(d) == -1) {
return z(d);
}
else {
return "white";
}
}
else {
return z(d);
}
})
.duration(100);
}
});
</script>
State,Under 5 Years,5 to 13 Years,14 to 17 Years,18 to 24 Years,25 to 44 Years,45 to 64 Years,65 Years and Over
CA,2704659,4499890,2159981,3853788,10604510,8819342,4114496
TX,2027307,3277946,1420518,2454721,7017731,5656528,2472223
NY,1208495,2141490,1058031,1999120,5355235,5120254,2607672
FL,1140516,1938695,925060,1607297,4782119,4746856,3187797
IL,894368,1558919,725973,1311479,3596343,3239173,1575308
PA,737462,1345341,679201,1203944,3157759,3414001,1910571

Tooltip for svg heatmap/colorscale in d3js

I am adapting this gradient example in AngularJS. Here is a bit of the dataset I'm using:
var stays=[
{
day:2,
hour:1,
time_spent:127
},
{
day:4,
hour:1,
time_spent:141
},
{
day:1,
hour:1,
time_spent:134
},
{
day:5,
hour:1,
time_spent:174
},
{
day:3,
hour:1,
time_spent:131
},
{
day:6,
hour:1,
time_spent:333
}];
The problem is that I want to construct a tooltip for each of the squares that are created in the heatmap. The tooltip is here:
var heatMap = svg.selectAll(".hour")
.data(stays)
.enter().append("rect")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("stroke-width", 0.8)
.style("fill", function(d) { return colorScale(d.time_spent); })
.on("mouseover", function(d, i) {
// Construct tooltip
var tooltip_html = '';
tooltip_html += '<div class="header"><strong>' + 'Stays' + ' </strong></div><br>';
// Add info to the tooltip
angular.forEach(stays, function (d) {
tooltip_html += '<div><span><strong>' + makeid() + '</strong></span>';
tooltip_html += '<span>' + ' ' + d.time_spent + '</span></div>';
console.log(d.time_spent);
}, days);
// Set tooltip width
tooltip.html(tooltip_html)
.style("width", 300 + "px")
.style("left", (d3.event.layerX+10) + "px")
.style("top", (d3.event.layerY+10) + "px");
// Tooltip transition and more styling
tooltip.style('display', 'block')
.transition()
.ease('ease-in')
.duration(100)
.style("opacity", .9);
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(100)
.ease('ease-in')
.style('opacity', 0);
});
The idea here is, for each square that I visit, the tooltip will show the labels associated (I'm still not using labels but they are going to be part of the dataset I've shown, I'm using the makeid() function to create random names) to that square, together with a breakdown of the associated time_spent data. With what I'm using now it is writing the full list of numbers and not the ones associated to each square. Ideas? Thank you.
Rather than building tootip HTML for each cell, consider attaching the data to each cell rect. Create a single data div and fill it when the cursor moves over the cell.
I added this to the heatmap gradient example. Give it a try.
var accidents=[{day:2,hour:1,count:127},{day:4,hour:1,count:141},{day:1,hour:1,count:134},{day:5,hour:1,count:174},{day:3,hour:1,count:131},{day:6,hour:1,count:333},{day:7,hour:1,count:311},{day:2,hour:2,count:79},{day:4,hour:2,count:99},{day:1,hour:2,count:117},{day:5,hour:2,count:123},{day:3,hour:2,count:92},{day:6,hour:2,count:257},{day:7,hour:2,count:293},{day:2,hour:3,count:55},{day:4,hour:3,count:73},{day:1,hour:3,count:107},{day:5,hour:3,count:89},{day:3,hour:3,count:66},{day:6,hour:3,count:185},{day:7,hour:3,count:262},{day:2,hour:4,count:39},{day:4,hour:4,count:67},{day:1,hour:4,count:59},{day:5,hour:4,count:83},{day:3,hour:4,count:45},{day:6,hour:4,count:180},{day:7,hour:4,count:220},{day:2,hour:5,count:48},{day:4,hour:5,count:57},{day:1,hour:5,count:73},{day:5,hour:5,count:76},{day:3,hour:5,count:72},{day:6,hour:5,count:168},{day:7,hour:5,count:199},{day:2,hour:6,count:129},{day:4,hour:6,count:102},{day:1,hour:6,count:129},{day:5,hour:6,count:140},{day:3,hour:6,count:117},{day:6,hour:6,count:148},{day:7,hour:6,count:193},{day:2,hour:7,count:314},{day:4,hour:7,count:284},{day:1,hour:7,count:367},{day:5,hour:7,count:270},{day:3,hour:7,count:310},{day:6,hour:7,count:179},{day:7,hour:7,count:192},{day:2,hour:8,count:806},{day:4,hour:8,count:811},{day:1,hour:8,count:850},{day:5,hour:8,count:609},{day:3,hour:8,count:846},{day:6,hour:8,count:208},{day:7,hour:8,count:144},{day:2,hour:9,count:1209},{day:4,hour:9,count:1214},{day:1,hour:9,count:1205},{day:5,hour:9,count:960},{day:3,hour:9,count:1073},{day:6,hour:9,count:286},{day:7,hour:9,count:152},{day:2,hour:10,count:750},{day:4,hour:10,count:808},{day:1,hour:10,count:610},{day:5,hour:10,count:655},{day:3,hour:10,count:684},{day:6,hour:10,count:482},{day:7,hour:10,count:253},{day:2,hour:11,count:591},{day:4,hour:11,count:593},{day:1,hour:11,count:573},{day:5,hour:11,count:695},{day:3,hour:11,count:622},{day:6,hour:11,count:676},{day:7,hour:11,count:326},{day:2,hour:12,count:653},{day:4,hour:12,count:679},{day:1,hour:12,count:639},{day:5,hour:12,count:736},{day:3,hour:12,count:687},{day:6,hour:12,count:858},{day:7,hour:12,count:402},{day:2,hour:13,count:738},{day:4,hour:13,count:749},{day:1,hour:13,count:631},{day:5,hour:13,count:908},{day:3,hour:13,count:888},{day:6,hour:13,count:880},{day:7,hour:13,count:507},{day:2,hour:14,count:792},{day:4,hour:14,count:847},{day:1,hour:14,count:752},{day:5,hour:14,count:1033},{day:3,hour:14,count:942},{day:6,hour:14,count:983},{day:7,hour:14,count:636},{day:2,hour:15,count:906},{day:4,hour:15,count:1031},{day:1,hour:15,count:954},{day:5,hour:15,count:1199},{day:3,hour:15,count:1014},{day:6,hour:15,count:1125},{day:7,hour:15,count:712},{day:2,hour:16,count:1101},{day:4,hour:16,count:1158},{day:1,hour:16,count:1029},{day:5,hour:16,count:1364},{day:3,hour:16,count:1068},{day:6,hour:16,count:1062},{day:7,hour:16,count:736},{day:2,hour:17,count:1303},{day:4,hour:17,count:1426},{day:1,hour:17,count:1270},{day:5,hour:17,count:1455},{day:3,hour:17,count:1407},{day:6,hour:17,count:883},{day:7,hour:17,count:666},{day:2,hour:18,count:1549},{day:4,hour:18,count:1653},{day:1,hour:18,count:1350},{day:5,hour:18,count:1502},{day:3,hour:18,count:1507},{day:6,hour:18,count:830},{day:7,hour:18,count:652},{day:2,hour:19,count:998},{day:4,hour:19,count:1070},{day:1,hour:19,count:787},{day:5,hour:19,count:1027},{day:3,hour:19,count:1019},{day:6,hour:19,count:575},{day:7,hour:19,count:519},{day:2,hour:20,count:661},{day:4,hour:20,count:756},{day:1,hour:20,count:596},{day:5,hour:20,count:730},{day:3,hour:20,count:648},{day:6,hour:20,count:494},{day:7,hour:20,count:486},{day:2,hour:21,count:431},{day:4,hour:21,count:539},{day:1,hour:21,count:430},{day:5,hour:21,count:509},{day:3,hour:21,count:457},{day:6,hour:21,count:443},{day:7,hour:21,count:421},{day:2,hour:22,count:352},{day:4,hour:22,count:428},{day:1,hour:22,count:362},{day:5,hour:22,count:462},{day:3,hour:22,count:390},{day:6,hour:22,count:379},{day:7,hour:22,count:324},{day:2,hour:23,count:329},{day:4,hour:23,count:381},{day:1,hour:23,count:293},{day:5,hour:23,count:393},{day:3,hour:23,count:313},{day:6,hour:23,count:374},{day:7,hour:23,count:288},{day:2,hour:24,count:211},{day:4,hour:24,count:249},{day:1,hour:24,count:204},{day:5,hour:24,count:417},{day:3,hour:24,count:211},{day:6,hour:24,count:379},{day:7,hour:24,count:203}];
///////////////////////////////////////////////////////////////////////////
//////////////////// Set up and initiate svg containers ///////////////////
///////////////////////////////////////////////////////////////////////////
var days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
times = d3.range(24);
var margin = {
top: 170,
right: 50,
bottom: 70,
left: 50
};
var width = Math.max(Math.min(window.innerWidth, 1000), 500) - margin.left - margin.right - 20,
gridSize = Math.floor(width / times.length),
height = gridSize * (days.length+2);
//SVG container
var svg = d3.select('#trafficAccidents')
.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 + ")");
//Reset the overall font size
var newFontSize = width * 62.5 / 900;
d3.select("html").style("font-size", newFontSize + "%");
///////////////////////////////////////////////////////////////////////////
//////////////////////////// Draw Heatmap /////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Based on the heatmap example of: http://blockbuilder.org/milroc/7014412
var colorScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })/2, d3.max(accidents, function(d) {return d.count; })])
.range(["#FFFFDD", "#3E9583", "#1F2D86"])
//.interpolate(d3.interpolateHcl);
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 8 && i <= 17) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data(accidents)
.enter().append("rect")
//----attach data to rect---
.attr("data","This is the data for this cell")
.attr("onmouseover","showData(evt)")
.attr("onmouseout","hideData(evt)")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("fill", function(d) { return colorScale(d.count); });
//Append title to the top
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", -90)
.style("text-anchor", "middle")
.text("Number of Traffic accidents per Day & Hour combination");
svg.append("text")
.attr("class", "subtitle")
.attr("x", width/2)
.attr("y", -60)
.style("text-anchor", "middle")
.text("The Netherlands | 2014");
//Append credit at bottom
svg.append("text")
.attr("class", "credit")
.attr("x", width/2)
.attr("y", gridSize * (days.length+1) + 80)
.style("text-anchor", "middle")
.text("Based on Miles McCrocklin's Heatmap block");
///////////////////////////////////////////////////////////////////////////
//////////////// Create the gradient for the legend ///////////////////////
///////////////////////////////////////////////////////////////////////////
//Extra scale since the color scale is interpolated
var countScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })])
.range([0, width])
//Calculate the variables for the temp gradient
var numStops = 10;
countRange = countScale.domain();
countRange[2] = countRange[1] - countRange[0];
countPoint = [];
for(var i = 0; i < numStops; i++) {
countPoint.push(i * countRange[2]/(numStops-1) + countRange[0]);
}//for i
//Create the gradient
svg.append("defs")
.append("linearGradient")
.attr("id", "legend-traffic")
.attr("x1", "0%").attr("y1", "0%")
.attr("x2", "100%").attr("y2", "0%")
.selectAll("stop")
.data(d3.range(numStops))
.enter().append("stop")
.attr("offset", function(d,i) {
return countScale( countPoint[i] )/width;
})
.attr("stop-color", function(d,i) {
return colorScale( countPoint[i] );
});
///////////////////////////////////////////////////////////////////////////
////////////////////////// Draw the legend ////////////////////////////////
///////////////////////////////////////////////////////////////////////////
var legendWidth = Math.min(width*0.8, 400);
//Color Legend container
var legendsvg = svg.append("g")
.attr("class", "legendWrapper")
.attr("transform", "translate(" + (width/2) + "," + (gridSize * days.length + 40) + ")");
//Draw the Rectangle
legendsvg.append("rect")
.attr("class", "legendRect")
.attr("x", -legendWidth/2)
.attr("y", 0)
//.attr("rx", hexRadius*1.25/2)
.attr("width", legendWidth)
.attr("height", 10)
.style("fill", "url(#legend-traffic)");
//Append title
legendsvg.append("text")
.attr("class", "legendTitle")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "middle")
.text("Number of Accidents");
//Set scale for x-axis
var xScale = d3.scale.linear()
.range([-legendWidth/2, legendWidth/2])
.domain([ 0, d3.max(accidents, function(d) { return d.count; })] );
//Define x-axis
var xAxis = d3.svg.axis()
.orient("bottom")
.ticks(5)
//.tickFormat(formatPercent)
.scale(xScale);
//Set up X axis
legendsvg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (10) + ")")
.call(xAxis);
//--show/hide data---
function showData(evt)
{
var target=evt.target
target.setAttribute("opacity",".8")
//---locate dataDiv near cursor--
var x = evt.clientX;
var y = evt.clientY;
//---scrolling page---
var offsetX=window.pageXOffset
var offsetY=window.pageYOffset
dataDiv.style.left=10+x+offsetX+"px"
dataDiv.style.top=20+y+offsetY+"px"
//---data--
var data=target.getAttribute("data")
//---format as desired---
var html=data
dataDiv.innerHTML=html
dataDiv.style.visibility="visible"
}
function hideData(evt)
{
dataDiv.style.visibility="hidden"
var target=evt.target
target.removeAttribute("opacity")
}
<head>
<meta charset="utf-8">
<!-- D3.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<!-- Google Font -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400' rel='stylesheet' type='text/css'>
<style>
html { font-size: 62.5%; }
body {
font-size: 1rem;
font-family: 'Open Sans', sans-serif;
font-weight: 400;
fill: #8C8C8C;
text-align: center;
}
.timeLabel, .dayLabel {
font-size: 1.6rem;
fill: #AAAAAA;
font-weight: 300;
}
text.axis-workweek, text.axis-worktime {
fill: #404040;
font-weight: 400;
}
.title {
font-size: 2.8rem;
fill: #4F4F4F;
font-weight: 300;
}
.subtitle {
font-size: 1.4rem;
fill: #AAAAAA;
font-weight: 300;
}
.credit {
font-size: 1.2rem;
fill: #AAAAAA;
font-weight: 400;
}
.axis path, .axis tick, .axis line {
fill: none;
stroke: none;
}
text {
font-size: 1.2rem;
fill: #AAAAAA;
font-weight: 400;
}
.legendTitle {
font-size: 1.6rem;
fill: #4F4F4F;
font-weight: 300;
}
</style>
</head>
<body>
<div id="trafficAccidents"></div>
<div id=dataDiv style='box-shadow: 4px 4px 4px #888888;-webkit-box-shadow:2px 3px 4px #888888;padding:2px;position:absolute;top:0px;left:0px;visibility:hidden;background-color:linen;border: solid 1px black;border-radius:5px;'></div>
</body>
I think you may be making this too complex.
Try using foxToolTip.js
https://github.com/MichaelRFox/foxToolTip.jS
After you create your unique I'd just use the .each method to add a unique tooltip.

Changing Data in d3 Based on Selection Input

I am currently building a graph using d3.js as well as HTML. I am trying to input interactivity by adding a selector which changes the displayed data based on your selection. I am not sure at all how to make the selector change which data is being used.
<!DOCTYPE html>
<html>
<head>
<meta><meta http-equiv="refresh" content="90">
<meta name="description" content="Drawing Shapes w/ D3 - " />
<meta charset="utf-8">
<title>Resources per Project</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
h1 {
font-size: 35px;
color: darkgrey;
font-family: Helvetica;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: black;
}
h2 {
font-size: 20px;
color: black;
font-family: Helvetica;
text-decoration: underline;
margin-left: 290px;
margin-top: 2px;
}
</style>
</head>
<body>
<h1>Resources used per Project</h1>
<p>Choose Month:
<select id="label-option">
<option value="April">April</option>
<option value="May">May</option>
<option value="June">June</option>
<option value="July">July</option>
<option value="August">August</option>
<option value="September">September</option>
</select>
<script type="text/javascript">
var width = 800
var height = 500
var emptyVar = 0
var dataArrayProjects = ['2G','An','At','Au','AW','Ch','CI','CN']
var April = [0.35,1.66,3.04,1.54,3.45,2.56,2.29,1.37]
var May = [0.36,1.69,3.08,1.54,3.62,2.61,2.22,1.44]
var June = [0.34,1.7,3.08,1.63,3.66,2.68,2.24,1.51]
var July = [0.3,1.72,3.17,1.67,3.56,2.56,2.17,1.44]
var August = [0.28,1.79,3.18,1.71,3.62,2.73,2.26,1.54]
var September = [0.23,1.74,3.12,1.61,3.66,2.71,2.2,1.48]
var widthScale = d3.scale.linear()
.domain([0, 4])
.range([0, width-60]);
var heightScale = d3.scale.ordinal()
.domain(dataArrayProjects)
.rangePoints([10, height-85]);
var color = d3.scale.linear()
.domain([0,4])
.range(["#000066", "#22abff"])
var axis = d3.svg.axis()
.ticks("10")
.scale(widthScale);
var yAxis = d3.svg.axis()
.scale(heightScale)
.orient("left");
var canvas = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40, 0)");
var bars = canvas.selectAll("rect")
.data(April)
.enter()
.append("rect")
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) { return color(d) })
.attr("y", function(d, i) { return i * 55 })
canvas.append("g")
.attr("transform", "translate(0, 430)")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.call(axis);
canvas.append("g")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.style("fill", "black")
.attr("class", "y axis")
.call(yAxis);
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) { return widthScale(d); })
</script>
<h2>Resources</h2>
</body>
</html>
So you know the variables April, May, June, July, August and September are the ones I would like it to change between and the .data selector in the "bars" variable is where the data should be changing between months.
Thanks in advance!
You can attach a listener to the select which will be notified on change of the select.
d3.select("#label-option").on("change", change);//attache listener
//on change update bars.
function change() {
var data = April;
if (this.selectedIndex == 1){
data = May;//return may Data
} else if (this.selectedIndex == 2){
data = June;//return June Data
} else if (this.selectedIndex == 3){
data = July;
} else if (this.selectedIndex == 4){
data = August;
} else if (this.selectedIndex == 5){
data = September;
}
//select all bars and set the new data
canvas.selectAll("rect")
.data(data)
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d) {
return color(d)
})
.attr("y", function(d, i) {
return i * 55
})
bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);//transition to new width
})
}
working code here

D3.js Bar Chart

HTML
<div id="searchVolume"></div>
CSS
#tooltip {
position: absolute;
width: 50px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 12px;
line-height: 16px;
}
.indent{
padding-left: 5px;
}
rect {
-moz-transition: all 0.3s;
-webkit-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
}
rect:hover{
fill: orange;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
Script
var margin = {top: 25, right: 40, bottom: 35, left: 85},
w = 500 - margin.left - margin.right,
h = 350 - margin.top - margin.bottom;
var padding = 10;
var colors = [ ["Morning", "#F64BEE"],
["Midday", "#25B244"],
["Afternoon", "#2BA3F4"],
["Evening","#FD7680"]];
var dataset = [
{ "Morning": 1400000, "Midday": 673000, "Afternoon": 43000, "Evening":50000},
{ "Morning": 165000, "Midday": 160000, "Afternoon": 21000, "Evening":23000 },
{"Morning": 550000, "Midday": 301000, "Afternoon": 34000, "Evening":43000},
{"Morning": 550320, "Midday": 351000, "Afternoon": 24000, "Evening":38000},
{"Morning": 55000, "Midday": 3010, "Afternoon": 24000, "Evening":43054},
{"Morning": 750000, "Midday": 401000, "Afternoon": 84000, "Evening":42100},
{"Morning": 578000, "Midday": 306000, "Afternoon": 54000, "Evening":43400},
];
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, w], 0.05);
// ternary operator to determine if global or local has a larger scale
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return Math.max(d.Morning,d.Midday,d.Afternoon,d.Evening);})])
.range([h, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
var commaFormat = d3.format(',');
//SVG element
var svg = d3.select("#searchVolume")
.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 + ")");
// Graph Bars
var sets = svg.selectAll(".set")
.data(dataset)
.enter()
.append("g")
.attr("class","set")
.attr("transform",function(d,i){
return "translate(" + xScale(i) + ",0)";
})
;
sets.append("rect")
.attr("class","Morning")
.attr("width", xScale.rangeBand()/4)
.attr("y", function(d) {
return yScale(d.Morning);
})
.attr("x", xScale.rangeBand()/4)
.attr("height", function(d){
return h - yScale(d.Morning);
})
.attr("fill", colors[0][1])
.append("text")
.text(function(d) {
return commaFormat(d.Morning);
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 4;
})
.attr("y", function(d) {
return h - yScale(d.Morning) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black")
;
sets.append("rect")
.attr("class","Midday")
.attr("width", xScale.rangeBand()/4)
.attr("y", function(d) {
return yScale(d.Midday);
})
.attr("height", function(d){
return h - yScale(d.Midday);
})
.attr("fill", colors[1][1])
.append("text")
.text(function(d) {
return commaFormat(d.Midday);
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 4;
})
.attr("y", function(d) {
return h - yScale(d.Midday) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red")
;
sets.append("rect")
.attr("class","Afternoon")
.attr("width", xScale.rangeBand()/4)
.attr("y", function(d) {
return yScale(d.Afternoon);
})
.attr("height", function(d){
return h - yScale(d.Afternoon);
})
.attr("fill", colors[2][1])
.append("text")
.text(function(d) {
return commaFormat(d.Afternoon);
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 4;
})
.attr("y", function(d) {
return h - yScale(d.Afternoon) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red")
;
sets.append("rect")
.attr("class","Evening")
.attr("width", xScale.rangeBand()/4)
.attr("y", function(d) {
return yScale(d.Evening);
})
.attr("height", function(d){
return h - yScale(d.Evening);
})
.attr("fill", colors[3][1])
.append("text")
.text(function(d) {
return commaFormat(d.Evening);
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 4;
})
.attr("y", function(d) {
return h - yScale(d.Evening) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red")
;
// xAxis
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + (h) + ")")
.call(xAxis)
;
// yAxis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0 ,0)")
.call(yAxis)
;
// xAxis label
svg.append("text")
.attr("transform", "translate(" + (w / 4) + " ," + (h + margin.bottom - 5) +")")
.style("text-anchor", "middle")
.text("Keyword");
//yAxis label
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (h / 4))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Searches");
// Title
svg.append("text")
.attr("x", (w / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Weekly Consumption");
// add legend
var legend = svg.append("g")
.attr("class", "legend")
//.attr("x", w - 65)
//.attr("y", 50)
.attr("height", 100)
.attr("width", 100)
.attr('transform', 'translate(-20,50)');
var legendRect = legend.selectAll('rect').data(colors);
legendRect.enter()
.append("rect")
.attr("x", w - 65)
.attr("width", 10)
.attr("height", 10);
legendRect
.attr("y", function(d, i) {
return i * 20;
})
.style("fill", function(d) {
return d[1];
});
var legendText = legend.selectAll('text').data(colors);
legendText.enter()
.append("text")
.attr("x", w - 52);
legendText
.attr("y", function(d, i) {
return i * 20 + 9;
})
.text(function(d) {
return d[0];
});
D3 Fiddle
In the above fiddle, I have attempted to make a bar chart using d3.js library. I am stuck on following basic things which shouldn't even take much time. I am not able to grasp the functions of d3. You can play around with the fiddle and any help would be hugely beneficial:
1. I want four different bars grouped on a single x value. Like for '0' there would be four of them unlike the current one where it is merging everything into two.
2. Change the content of x-axis from numbers to days like from Monday to Friday.
3. For y-axis, I am trying to display the values like, instead of 20000, it should show 20k and the bar should recognise that while dynamically creating it. Is this possible?
Any help would be greatly beneficial. I couldn't figure it out.
The main issue is that you start joining your data correctly but afterwards you start doing some manual stuff that could have been solved by using the data function to join the data into your child elements. Let me explain:
First of all we will need two x axis scales, one to hold our days domain and the other one will hold our time domain using as rangeRoundBands the days scale.
var day_scale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, w], 0.05);
var time_scale = d3.scale.ordinal();
time_scale.domain(['Morning', 'Midday', 'Afternoon', 'Evening'])
.rangeRoundBands([0, day_scale.rangeBand()]);
Let's tackle the x axis formatting while we are setting up our scales. I created an array of days and within our tickFormat function lets return the value in the array based in the index of the data we passed.
var days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
var day_axis = d3.svg.axis()
.scale(day_scale)
.orient("bottom")
.tickFormat(function(d,i) {
return days[i];
});
Now the y axis formatting, we can solve this by using a d3.formatPrefix more info here
var prefix = d3.formatPrefix(1.21e9);
var searches_axis = d3.svg.axis()
.scale(searches_scale)
.orient("left")
.ticks(5)
.tickFormat(function(d) {
var prefix = d3.formatPrefix(d);
return prefix.scale(d) + prefix.symbol;
});
Now lets skip our svg and axis config, to get to the data join issue:
var day_groups = svg.selectAll(".day-group")
.data(dataset) // join data to our selection
.enter().append("g")
.attr("class", function(d, i) {
return 'day-group day-group-' + i;
})
.attr("transform", function(d, i) {
// position a g element with our day_scale and data index
return "translate(" + day_scale(i) + ",0)";
});
With our day-groups positioned correctly now we are able to append our time data.
var times_g = day_groups.selectAll(".time-group")
.data(function(d) {
// this is the tricky part, we are creating an array of
// objects with key (time...'Morning', 'Midday', 'Afternoon', 'Evening')
// and value (the value of the time)
// in order to create a time group for each time event
return Object.keys(d).map(function(key) {
return {
key: key,
value: d[key]
}
});
})
.enter().append("g")
.attr("class", function(d) {
return 'time-group time-group-' + d.key;
})
.attr("transform", function(d) {
// use our time scale to position
return "translate(" + time_scale(d.key) + ",0)";
});
Now lets add our rects!
var rects = times_g.selectAll('.rect')
.data(function(d) {
// use as data our object
return [d];
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", time_scale.rangeBand()) // get width of rect based in our time_scale
.attr("x", function(d) {
return 0; // returning 0 since the group is in charge of positioning
})
.attr("y", function(d) {
return searches_scale(d.value); // use our y_scale
})
.attr("height", function(d) {
return h - searches_scale(d.value); // use our y_scale
})
.style("fill", function(d) {
return colors[d.key]; // map colors by using an object
});
Mapping color object:
var colors = {
"Morning":"#F64BEE",
"Midday": "#25B244",
"Afternoon": "#2BA3F4",
"Evening": "#FD7680"
};
If you have any doubt of how this works here is the updated jsfiddle: https://jsfiddle.net/706gsjfg/3/ (I removed certain things, but you can add them later I guess)

In D3, Bar graph's text labels are not updated after the inclusion of additional data

I am making a bar graph. As a user loads the page, they will see a bar graph with 20 bars in total, and each bar comes with a label indicating the numerical value the bar represents (as shown below).
If the user clicks on a line of text on top of the graph, the graph will update to include two additional randomly generated bars. For some reason, I cannot get the graph to also update the labels for the new bars. For example, after one click on the text, I get something shown below:
The relevant code is below, and the complete code is here: http://jsfiddle.net/55DLc/9/
var texts = svg.selectAll("text").data(dataset);
texts.enter()
.append("text")
.text(function(d){ return d; })
.attr("x", w - padding)
.attr("y", function( d ){return yScale( d ) - 2;})
.attr("text-anchor", "middle")
.attr("fill", "red");
texts.transition()
.duration(500)
.text(function(d){return d;})
.attr("x", function(d, i){return xScale( i ) + xScale.rangeBand()/2;})
.attr("y", function( d ){return yScale( d ) - 2;})
.attr("text-anchor", "middle")
.attr("fill", "red");
In your update, this line:
var texts = svg.selectAll("text")
.data(dataset);
is not only selecting your text labels on top of the bars but it also selecting the text labels that are part of the axis.
Easy fix is to assign a unique class to your text labels and select on that to update them.
Here's it all fixed up:
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/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;
fill: black;
font-size: 13px;
}
div.bar {
display: inline-block;
width: 20px;
background-color: teal;
}
</style>
</head>
<body>
<p>Click on this text to update the chart</p>
<script type="text/javascript">
w = 600, h = 500, padding = 30;
var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([padding, w - padding], 0.05);
var yScale = d3.scale.linear()
.domain([ 0,
d3.max(dataset)])
.range([ h - padding, padding ]);
var xAxis = d3.svg.axis()
.scale( xScale )
.orient("bottom")
.ticks( 10 );
var yAxis = d3.svg.axis()
.scale( yScale )
.orient("left");
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.transition()
.delay(function(d, i){
return i * 100;
})
.duration(500)
.attr("x", function(d, i){
return xScale(i)
})
.attr("y", function( d ){
return yScale( d );
})
.attr("width", xScale.rangeBand())
.attr("height", function(d){
return h - yScale( d ) - padding - 1;
})
.attr("fill", function( d ){
return "rgb(150, 220, " + (d * 10) + ")";
});
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("class","myLabels")
.transition()
.delay(function(d, i){
return i * 100;
})
.text(function(d){
return d;
})
.attr("x", function(d, i){
return xScale( i ) + xScale.rangeBand()/2;
})
.attr("y", function( d ){
return yScale( d ) - 2;
})
.attr("text-anchor", "middle")
.attr("fill", "red");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + (h - padding) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (padding) + ", 0)")
.call(yAxis);
d3.select("p")
.on("click", function(){
for(var i = 0; i < 2; i++ ){
var newNumber = Math.floor(Math.random()*25 );
dataset.push( newNumber );
}
xScale.domain(d3.range(dataset.length));
yScale.domain([ 0, d3.max(dataset)]);
var bars = svg.selectAll("rect")
.data(dataset);
bars.enter()
.append("rect")
.attr("x", w - padding)
.attr("y", function( d ){
return yScale( d ) ;
})
.attr("width", xScale.rangeBand())
.attr("height", function(d){
return h - yScale( d ) - padding;
})
.attr("fill", function( d ){
return "rgb(150, 220, " + (d * 10) + ")";
})
bars.transition()
.duration(500)
.attr("x", function(d, i){
return xScale( i );
})
.attr("y", function( d ){
return yScale( d );
})
.attr("width", xScale.rangeBand())
.attr("height", function(d){
return h - yScale( d ) - padding - 1;
});
var texts = svg.selectAll(".myLabels")
.data(dataset);
texts.enter()
.append("text")
.attr("class","myLabels")
.text(function(d){ return d; })
.attr("x", w - padding)
.attr("y", function( d ){
return yScale( d ) - 2;
})
.attr("text-anchor", "middle")
.attr("fill", "red");
texts.transition()
.duration(500)
.text(function(d){
return d;
})
.attr("x", function(d, i){
return xScale( i ) + xScale.rangeBand()/2;
})
.attr("y", function( d ){
return yScale( d ) - 2;
})
.attr("text-anchor", "middle")
.attr("fill", "red");
svg.select( ".x.axis")
.transition()
.duration(1000)
.call(xAxis);
svg.select( ".y.axis")
.transition()
.duration(1000)
.call(yAxis);
});
</script>
</body>
</html>

Categories