Related
I am trying to add text on each bar in grouped bar chart. but it is not showing & no error is there on console.
I am using the sample code from https://bl.ocks.org/bricedev/0d95074b6d83a77dc3ad
I tried below code:
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
//display: none; //to show x axis
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 40, right: 60, bottom: 40, left: 40},
width = 560 - margin.left - margin.right,
height = 300 - 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 xAxis = d3.svg.axis()
.scale(x0)
.tickSize(0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var color = d3.scale.ordinal()
.range(["#ca0020","#f4a582","#d5d5d5","#92c5de","#0571b0"]);
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 + ")");
d3.json("data.json", function(error, data) {
var categoriesNames = data.map(function(d) { return d.categorie; });
var rateNames = data[0].values.map(function(d) { return d.rate; });
x0.domain(categoriesNames);
x1.domain(rateNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(categorie) { return d3.max(categorie.values, function(d) { return d.value; }); })]);
//Graph Title
svg.append("text")
.attr("transform", "translate(100,0)")
.attr("x", 100)
.attr("y", -20)
.attr("font-size", "24px")
.text("Grouped Bar Chart");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.attr("transform", "translate(" + width + ",10)")
.text("Months");
svg.append("g")
.attr("class", "y axis")
.style('opacity','0')
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.text("Incidents");
svg.select('.y').transition().duration(500).delay(1300).style('opacity','1');
var slice = svg.selectAll(".slice")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform",function(d) { return "translate(" + x0(d.categorie) + ",0)"; });
//draw bars
slice.selectAll("rect")
.data(function(d) { return d.values; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.rate); })
.style("fill", function(d) { return color(d.rate) })
.attr("y", function(d) { return y(0); })
.attr("height", function(d) { return height - y(0); })
.on("mouseover", function(d) {
d3.select(this).style("fill", d3.rgb(color(d.rate)).darker(2));
})
.on("mouseout", function(d) {
d3.select(this).style("fill", color(d.rate));
});
slice.selectAll("text")
.data(function(d) {return d.values ;})
.enter()
.append("text")
.attr("x", function(d) { return x1(d.rate); })
.attr("y", function(d) { return ( y(0) ) ; })
.text(function(d) {
return (d.value); // Value of the text
});
slice.selectAll("rect")
.transition()
.delay(function (d) {return Math.random()*1000;})
.duration(1000)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
//Legend
var legend = svg.selectAll(".legend")
.data(data[0].values.map(function(d) { return d.rate; }).reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d,i) { return "translate(60," + i * 20 + ")"; })
.style("opacity","0");
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d) { return color(d); });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {return d; });
legend.transition().duration(500).delay(function(d,i){ return 1300 + 100 * i; }).style("opacity","1");
});
</script>
</body>
</html>
But the output is output after adding block
It is showing object object in output.
Please help.
output of code is here
You're appending to slice, which is a selection of all the bar groups, not the bars themselves. Try something like this to get started:
slice.selectAll("text")
.data(function(d) { return d.values; })
.enter().append("text")
.attr("x", function(d) { return x1(d.rate); })
.attr("y", function(d) { return y(d.value); })
.text(function(d) { return d.value })
Having trouble using an external file data.json for use on a bar chart with a brush. This seems to be a scope issue.
I am using,
d3.json("data.json", function(error, data) {...});
to read in the json file. Inside this main chart and brush chart are drawn. And there is a call to the variable 'brush', which is outside of d3.json() and in that var there is a call to the brush function which is also outside of d3.json(). The 'data' cannot be read inside the brush function. I tried passing data as a parameter, brush(data) but that doesn't work.
The error I get is,
Uncaught ReferenceError: data is not defined
This error refers to line 226 which is in the brush function and looks like this,
.data(data.filter(function(d) {....
and is the first use of 'data' in the brush function.
This is set up the same as Bostock's example Brush & Zoom
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
body {
font-family: avenir next, sans-serif;
font-size: 12px;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
.axis {
stroke-width: 0.5px;
stroke: #888;
font: 10px avenir next, sans-serif;
}
.axis>path {
stroke: #888;
}
</style>
<body>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var margin = {
top: 20,
right: 20,
bottom: 90,
left: 50
},
margin2 = {
top: 230,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom,
height2 = 300 - margin2.top - margin2.bottom;
var x = d3.scaleBand().range([0, width]).padding(0.1),
x2 = d3.scaleBand().range([0, width]).padding(0.1),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x).tickSize(0),
xAxis2 = d3.axisBottom(x2).tickSize(0),
yAxis = d3.axisLeft(y).tickSize(0);
var brush = d3.brushX()
.extent([
[0, 0],
[width, height2]
])
// .on("start brush end", brushed);
.on("brush", brushed);
var zoom = d3.zoom()
.scaleExtent([1, 2])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
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("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
focus.append("text") // yAxis label
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Distance in meters");
svg.append("text") // xAxis label
.attr("transform",
"translate(" + ((width + margin.right + margin.left) / 2) + " ," +
(height + margin.top + margin.bottom) + ")")
.style("text-anchor", "middle")
.text("Date");
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom); //see var zoom above
focus.append("g") //append xAxis to main chart
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
d3.json("data.json", function(error, data) {
if (error) throw error;
focus.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.distance;
})])
.range([height, 0])).tickSize(0));
data.forEach(function(d) {
d.distance = +d.distance;
return d;
},
function(error, data) {
if (error) throw error;
});
x.domain(data.map(function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.distance;
})]);
x2.domain(x.domain());
y2.domain(y.domain());
//********* Main ar Chart ****************
var rects = focus.append("g");
rects.attr("clip-path", "url(#clip)");
rects.selectAll("rects")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rects")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.distance);
});
// //********* Brush Bar Chart ****************
var rects = context.append("g"); //draw bar chart in brush
rects.attr("clip-path", "url(#clip)");
rects.selectAll("rect")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rectss")
.attr("x", function(d) {
return x2(d.date);
})
.attr("y", function(d) {
return y2(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height2 - y2(d.distance);
});
context.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
}); //closes d3.json()
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
// get bounds of selection
var s = d3.event.selection,
nD = [];
x2.domain().forEach((d) => { //not as smooth as I'd like it
var pos = x2(d) + x2.bandwidth() / 2;
if (pos > s[0] && pos < s[1]) {
nD.push(d);
}
});
x.domain(nD);
focus.selectAll(".rects")
.remove().exit()
.data(data.filter(function(d) {
return nD.indexOf(d.date) > -1
}))
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rects")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.distance);
});
focus.select(".x-axis").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
};
function zoomed() {};
</script>
A small part of the data.json
[{
"date": "A",
"distance": "1100"
},
{
"date": "B",
"distance": "1500"
},
{
"date": "C",
"distance": "2000"
},
{
"date": "D",
"distance": "2500"
},
{
"date": "E",
"distance": "1975"
},
{
"date": "F",
"distance": "3000"
},
{
"date": "G",
"distance": "2100"
},
{
"date": "H",
"distance": "2100"
},
{
"date": "I",
"distance": "3300"
},
{
"date": "J",
"distance": "2000"
}
]
Any help would be greatly appreciated.
Thanks,
Addendum:
Why does this not work?
var data = null;
d3.json("data.json", function(error, data) {
if (error) throw error;
.....
)}
and this does work,
var data = null;
d3.json("data.json", function(error, newdata) {
if (error) throw error;
data = newdata;
.....});
Indeed you have an issue with your scope. The variable data is defined inside a function, so it can't be available out of this function. Here is the code to make it works :
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
body {
font-family: avenir next, sans-serif;
font-size: 12px;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
.axis {
stroke-width: 0.5px;
stroke: #888;
font: 10px avenir next, sans-serif;
}
.axis>path {
stroke: #888;
}
</style>
<body>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var margin = {
top: 20,
right: 20,
bottom: 90,
left: 50
},
margin2 = {
top: 230,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom,
height2 = 300 - margin2.top - margin2.bottom;
var x = d3.scaleBand().range([0, width]).padding(0.1),
x2 = d3.scaleBand().range([0, width]).padding(0.1),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x).tickSize(0),
xAxis2 = d3.axisBottom(x2).tickSize(0),
yAxis = d3.axisLeft(y).tickSize(0);
var brush = d3.brushX()
.extent([
[0, 0],
[width, height2]
])
// .on("start brush end", brushed);
.on("brush", brushed);
var zoom = d3.zoom()
.scaleExtent([1, 2])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
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("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
focus.append("text") // yAxis label
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Distance in meters");
svg.append("text") // xAxis label
.attr("transform",
"translate(" + ((width + margin.right + margin.left) / 2) + " ," +
(height + margin.top + margin.bottom) + ")")
.style("text-anchor", "middle")
.text("Date");
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom); //see var zoom above
focus.append("g") //append xAxis to main chart
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var data_global=null;
d3.json("data.json", function(error, data) {
if (error) throw error;
data_global=data;
focus.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.distance;
})])
.range([height, 0])).tickSize(0));
data.forEach(function(d) {
d.distance = +d.distance;
return d;
},
function(error, data) {
if (error) throw error;
});
x.domain(data.map(function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.distance;
})]);
x2.domain(x.domain());
y2.domain(y.domain());
//********* Main ar Chart ****************
var rects = focus.append("g");
rects.attr("clip-path", "url(#clip)");
rects.selectAll("rects")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rects")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.distance);
});
// //********* Brush Bar Chart ****************
var rects = context.append("g"); //draw bar chart in brush
rects.attr("clip-path", "url(#clip)");
rects.selectAll("rect")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rectss")
.attr("x", function(d) {
return x2(d.date);
})
.attr("y", function(d) {
return y2(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height2 - y2(d.distance);
});
context.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
}); //closes d3.json()
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
// get bounds of selection
var s = d3.event.selection,
nD = [];
x2.domain().forEach((d) => { //not as smooth as I'd like it
var pos = x2(d) + x2.bandwidth() / 2;
if (pos > s[0] && pos < s[1]) {
nD.push(d);
}
});
x.domain(nD);
focus.selectAll(".rects")
.remove().exit()
.data(data_global.filter(function(d) {
return nD.indexOf(d.date) > -1
}))
.enter().append("rect")
.style("fill", function(d) {
return "lightblue";
})
.style('stroke', 'gray')
.attr("class", "rects")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.distance);
});
focus.select(".x-axis").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
};
function zoomed() {};
</script>
I try to adapt the following script.
But unfortunately I can not match the data points to the legend on the x-axis?
How can I move the data points / the line to the right to match the legend on the x-axis?
Source is: http://mund-consulting.com/Blog/visualizing-web-page-views-using-d3js/
<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: 30, left: 40 },
width = 900,
height = 400;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.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>"+d.MonthName+": </strong>
<span style='color:black'>" + d.PageViews + "</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.csv("mc_monthly_pageview_2014.csv", function (error, data) {
x.domain(data.map(function (d) { return d.MonthName; }));
y.domain([0, d3.max(data, function (d) { return d.PageViews; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Page Views");
var line = d3.svg.line()
.x(function (d) { return x(d.MonthName); })
.y(function (d) { return y(d.PageViews); });
svg.selectAll("path.line")
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr("d", line(data));
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("cx", function (d) { return x(d.MonthName); })
.attr("cy", function (d) { return y(d.PageViews); })
.attr("r", 4.5)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
});
</script>
I found a solution.
Exchange
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
with
var x = d3.scale.ordinal()
.rangePoints([0, width]);
I am creating a D3 bar chart using below code .
<head>
<style>
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
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 + ")");
var data = [{"text":"A","value":50,"linkurl":"http://google.com"}, {"text":"B","value":100,"linkurl":"http://php.net"},{"text":"C","value":150,"linkurl":"http://drupal.org"}]
data.forEach(function(d) {
d.text = d.text;
d.value = +d.value;
d.linkurl = d.linkurl;
});
x.domain(data.map(function(d) { return d.text; }));
y.domain([0, d3.max(data, 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", "-.55em")
.attr("transform", "rotate(-45)" );
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("");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.text); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
svg.on("click", function (d) { //<-D
//var position = d3.mouse(svg.node());
window.location.href='http://google.com';
//window.location.href=d.linkurl;
});
</script>
</body>
And want to create a link on each bar.. for that I am using the code . It is working fine when I am using same URL for each bar but doesn't
for different URl for each bar...
var data = [{"text":"A","value":50,"linkurl":"http://google.com"},{"text":"B","value":100,"linkurl":"http://php.net"},{"text":"C","value":150,"linkurl":"http://drupal.org"}]
data.forEach(function(d) {
d.text = d.text;
d.value = +d.value;
d.linkurl = d.linkurl;
});
svg.on("click", function (d) { //<-D
//var position = d3.mouse(svg.node());
window.location.href='http://google.com';
//window.location.href=d.linkurl;
});
You have to bind the click listener to the bars (rectangles) instead of svg.
var bars = svg.selectAll("bar")
.data(data)
.enter()
.append("rect")
.style("fill", "steelblue")
.attr("x", function(d) {
return x(d.text);
}).attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.value);
}).attr("height", function(d) {
return height - y(d.value);
});
bars.on("click", function(d) {
window.location.href = d.linkurl;
});
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40
}, width = 600 - margin.left - margin.right, height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([ 0, width ], .05);
var y = d3.scale.linear().range([ height, 0 ]);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(10);
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 + ")");
var data = [ {
text: "A",
value: 50,
linkurl: "http://google.com"
}, {
text: "B",
value: 100,
linkurl: "http://php.net"
}, {
text: "C",
value: 150,
linkurl: "http://drupal.org"
} ];
data.forEach(function(a) {
a.text = a.text;
a.value = +a.value;
a.linkurl = a.linkurl;
});
x.domain(data.map(function(a) {
return a.text;
}));
y.domain([ 0, d3.max(data, function(a) {
return a.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", "-.55em")
.attr("transform", "rotate(-45)");
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("");
var bars = svg.selectAll("bar")
.data(data)
.enter()
.append("rect")
.style("fill", "steelblue")
.attr("x", function(a) {
return x(a.text);
}).attr("width", x.rangeBand())
.attr("y", function(a) {
return y(a.value);
}).attr("height", function(a) {
return height - y(a.value);
});
bars.on("click", function(a) {
window.location.href = a.linkurl;
});
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I'm trying to create a grouped bar chart that can include transitions. I referenced Mike Bostock's grouped bar chart example and have the bar chart transition working but can't get the axis to transition as well. What I'm referring to in this example is the state labels.
I tried following another example posted but I'm baffled as to why I can get it to work. For my example code the transition occurs on click of the SVG
Grouped Bar Chart Reference Example
Axis Reference Example
<!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: steelblue;
}
.x_axis path {
display: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
//Update the flips bars but not the axis
function update() {
var data_update = data.reverse()
x0.domain[data_update]
svg.selectAll(".state")
.data(data_update)
.transition()
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
svg.select(".x_axis")
.transition()
.call(xAxis);
}
d3.select("svg")
.on("click", update)
//The rest of the code
var data
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - 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(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
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 + ")");
d3.csv("data.csv", function(error, csv) {
data = csv
var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; });
data.forEach(function(d) {
d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x_axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "state")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.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); });
});
</script>
I'm a dummy and figured it out.
Calling the .domain method on an array of objects is useless. I forgot to map the object array to get the value of the states
x0.domain(data_update.map(function(d) { return d.State; }))
Full Code below for those curious
<!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: steelblue;
}
.x_axis path {
display: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var data
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - 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(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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 + ")");
d3.csv("data.csv", function(error, csv) {
data = csv
var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; });
data.forEach(function(d) {
d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x_axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Population");
var state = svg.selectAll(".state")
.data(data, function(d) {return d.State})
.enter().append("g")
.attr("class", "state")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.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); });
var legend = svg.selectAll(".legend")
.data(ageNames.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; });
});
//Update the flips bars
function update() {
data.reverse()
x0.domain(data.map(function(d) { return d.State; }))
svg.selectAll(".state")
.data(data, function(d) {return d.State})
.transition()
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
svg.select(".x_axis")
.transition()
.call(xAxis);
}
d3.select("svg")
.on("click", update)
</script>